mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into metadataReferences
This commit is contained in:
@@ -57,3 +57,4 @@ internal/
|
||||
!tests/cases/projects/NodeModulesSearch/**/*
|
||||
!tests/baselines/reference/project/nodeModules*/**/*
|
||||
.idea
|
||||
yarn.lock
|
||||
@@ -1,18 +1,22 @@
|
||||
|
||||
AbubakerB <abubaker_bashir@hotmail.com> # Abubaker Bashir
|
||||
Alexander <alexander@kuvaev.me># Alexander Kuvaev
|
||||
Aluan Haddad <aluanh@gmail.com>
|
||||
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>
|
||||
Anders Hejlsberg <andersh@microsoft.com> unknown <andersh@AndersX1.NOE.Nokia.com> unknown <andersh@andersh-yoga.redmond.corp.microsoft.com> Anders Hejlsberg <Anders Hejlsberg>
|
||||
about-code <about-code@users.noreply.github.com> # Andreas Martin
|
||||
Andrej Baran <andrej.baran@gmail.com>
|
||||
Andrew Ochsner <andrew.ochsner@wipro.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>
|
||||
Anubha Mathur <anubmat@microsoft.com> anubmat <anubmat@microsoft.com>
|
||||
Arnavion <arnavion@gmail.com> # Arnav Singh
|
||||
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>
|
||||
@@ -21,6 +25,7 @@ Basarat Ali Syed <basaratali@gmail.com> Basarat Syed <basaratali@gmail.com> basa
|
||||
Bill Ticehurst <billti@hotmail.com> Bill Ticehurst <billti@microsoft.com>
|
||||
Ben Duffield <jebavarde@gmail.com>
|
||||
Ben Mosher <me@benmosher.com>
|
||||
Benjamin Bock <bb@users.noreply.github.com>
|
||||
Blake Embrey <hello@blakeembrey.com>
|
||||
Bowden Kelly <wilkelly@microsoft.com>
|
||||
Brett Mayen <bmayen@midnightsnacks.net>
|
||||
@@ -37,6 +42,7 @@ 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>
|
||||
David Li <jiawei.davidli@gmail.com>
|
||||
David Sheldrick <david@futurice.com>
|
||||
David Souther <davidsouther@gmail.com>
|
||||
Denis Nedelyaev <denvned@gmail.com>
|
||||
Dick van den Brink <d_vandenbrink@outlook.com> unknown <d_vandenbrink@outlook.com> unknown <d_vandenbrink@live.com>
|
||||
@@ -45,6 +51,7 @@ 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>
|
||||
Erik McClenney <erikmcc@google.com>
|
||||
erictsangx <erictsangx@gmail.com> # Eric Tsang
|
||||
Ethan Rubio <ethanrubio@users.noreply.github.com>
|
||||
Evan Martin <martine@danga.com>
|
||||
@@ -52,6 +59,7 @@ Evan Sebastian <evanlhoini@gmail.com>
|
||||
Eyas <eyas.sharaiha@gmail.com> # Eyas Sharaiha
|
||||
Fabian Cook <faybecook@gmail.com>
|
||||
falsandtru <falsandtru@users.noreply.github.com> # @falsandtru
|
||||
flowmemo <flowmemo@outlook.com> # @flowmemo
|
||||
Frank Wallis <fwallis@outlook.com>
|
||||
František Žiacik <fziacik@gratex.com> František Žiacik <ziacik@gmail.com>
|
||||
Gabe Moothart <gmoothart@gmail.com>
|
||||
@@ -62,13 +70,19 @@ Graeme Wicksted <graeme.wicksted@gmail.com>
|
||||
Guillaume Salles <guillaume.salles@me.com>
|
||||
Guy Bedford <guybedford@gmail.com> guybedford <guybedford@gmail.com>
|
||||
Harald Niesche <harald@niesche.de>
|
||||
Homa Wong <homawong@gmail.com>
|
||||
Hendrik Liebau <mail@hendrik-liebau.de>
|
||||
Iain Monro <iain.monro@softwire.com>
|
||||
IgorNovozhilov <maildrakon@gmail.com> # Igor Novozhilov
|
||||
Ingvar Stepanyan <me@rreverser.com>
|
||||
impinball <impinball@gmail.com> # Isiah Meadows
|
||||
Iwata Hidetaka <iwata0303@gmail.com>
|
||||
Ivo Gabe de Wolff <ivogabe@ivogabe.nl>
|
||||
Jakub Młokosiewicz <hckr@users.noreply.github.com>
|
||||
James Whitney <james@whitney.io>
|
||||
James Henry <james@henry.sc>
|
||||
Jason Freeman <jfreeman@microsoft.com> Jason Freeman <JsonFreeman@users.noreply.github.com>
|
||||
Jason Jarrett <jason@elegantcode.com>
|
||||
Jason Killian <jkillian@palantir.com>
|
||||
Jason Ramsay <jasonra@microsoft.com> jramsay <jramsay@users.noreply.github.com>
|
||||
Jed Mao <jed.hunsaker@gmail.com>
|
||||
@@ -81,7 +95,9 @@ 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>
|
||||
Joel Day <joelday@gmail.com>
|
||||
Josh Abernathy <joshaber@gmail.com> joshaber <joshaber@gmail.com>
|
||||
Josh Goldberg <joshuakgoldberg@outlook.com>
|
||||
Josh Kalderimis <josh.kalderimis@gmail.com>
|
||||
Josh Soref <jsoref@users.noreply.github.com>
|
||||
Juan Luis Boya García <ntrrgc@gmail.com>
|
||||
@@ -95,22 +111,31 @@ Kanchalai Tanglertsampan <yuisu@microsoft.com> Yui T <yuisu@microsoft.com>
|
||||
Kanchalai Tanglertsampan <yuisu@microsoft.com> Yui <yuit@users.noreply.github.com>
|
||||
Kanchalai Tanglertsampan <yuisu@microsoft.com> Yui <yuisu@microsoft.com>
|
||||
Kanchalai Tanglertsampan <yuisu@microsoft.com> yui T <yuisu@microsoft.com>
|
||||
Kārlis Gaņģis <Knagis@users.noreply.github.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
|
||||
Kitson Kelly <me@kitsonkelly.com>
|
||||
Klaus Meinhardt <klaus.meinhardt1@gmail.com>
|
||||
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>
|
||||
Magnus Hiie <magnus.hiie@gmail.com>
|
||||
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>
|
||||
Matt McCutchen <rmccutch@mit.edu> Matt McCutchen <matt@mattmccutchen.net>
|
||||
Matt Bierner <matb@microsoft.com>
|
||||
MANISH-GIRI <manish.giri.me@gmail.com> # Manish Giri
|
||||
Max Deepfield <maxdeepfield@absolutefreakout.com>
|
||||
Micah Zoltu <micah@zoltu.net>
|
||||
Michael <maykelchiche@gmail.com>
|
||||
Mike Busyrev <busyrev@gmail.com>
|
||||
Mine Starks <minestarks@users.noreply.github.com> Mine Starks <mineyalc@microsoft.com>
|
||||
Mohamed Hegazy <mhegazy@microsoft.com>
|
||||
ncoley <nrcoley@gmail.com> # Natalie Coley
|
||||
Nathan Shively-Sanders <nathansa@microsoft.com>
|
||||
Nathan Yee <ny.nathan.yee@gmail.com>
|
||||
Nima Zahedi <nima.zahedee@gmail.com>
|
||||
@@ -133,12 +158,14 @@ Rado Kirov <radokirov@google.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>
|
||||
Richard Karmazín <richard@karmazin.cz>
|
||||
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>
|
||||
chico <chi187@gmail.com> # Sergey Rubanov
|
||||
Sheetal Nandi <shkamat@microsoft.com>
|
||||
Shengping Zhong <zhongsp@users.noreply.github.com>
|
||||
shyyko.serhiy@gmail.com <shyyko.serhiy@gmail.com> # Shyyko Serhiy
|
||||
@@ -146,6 +173,7 @@ Sam El-Husseini <samelh@microsoft.com>
|
||||
Simon Hürlimann <simon.huerlimann@cyt.ch>
|
||||
Slawomir Sadziak <slsadzia@microsoft.com>
|
||||
Solal Pirelli <solal.pirelli@gmail.com>
|
||||
Soo Jae Hwang <misoguy1985@gmail.com>
|
||||
Stan Thomas <stmsdn@norvil.net>
|
||||
Stanislav Sysoev <d4rkr00t@gmail.com>
|
||||
Steve Lucco <steveluc@users.noreply.github.com> steveluc <steveluc@microsoft.com>
|
||||
@@ -163,6 +191,7 @@ 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>
|
||||
Vadi Taslim <vadz77@hotmail.com>
|
||||
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>
|
||||
@@ -189,6 +218,7 @@ Aliaksandr Radzivanovich <aradzivanovich@gmail.com>
|
||||
BuildTools <FranklinWhale@users.noreply.github.com> # Franklin Tse
|
||||
ChogyDan <danielhollocher@gmail.com> # Daniel Hollocher
|
||||
Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com> Daniel Rosenwasser <drosen@microsoft.com>
|
||||
DLehenbauer <DLehenbauer@users.noreply.github.com> # Daniel Lehenbauer
|
||||
David Kmenta <david.kmenta@lmc.eu>
|
||||
E020873 <nicolas.henry-partner@arcelormittal.com> # Nicolas Henry
|
||||
Elisée Maurer <elisee@sparklinlabs.com>
|
||||
@@ -213,4 +243,9 @@ Tim Perry <tim.perry@softwire.com>
|
||||
Vidar Tonaas Fauske <vidartf@gmail.com>
|
||||
Viktor Zozulyak <zozulyakviktor@gmail.com>
|
||||
rix <rix@rixs-MacBook-Pro.local> # Richard Sentino
|
||||
rohitverma007 <rohitverma@live.ca> # Rohit Verma
|
||||
rohitverma007 <rohitverma@live.ca> # Rohit Verma
|
||||
rdosanjh <me@rajdeep.io> # Raj Dosanjh
|
||||
gdh1995 <gdh1995@qq.com> # Dahan Gong
|
||||
cedvdb <cedvandenbosch@gmail.com> # @cedvdb
|
||||
kpreisser <kpreisser@users.noreply.github.com> # K. Preißer
|
||||
e-cloud <saintscott119@gmail.com> # @e-cloud
|
||||
@@ -17,6 +17,7 @@ branches:
|
||||
only:
|
||||
- master
|
||||
- release-2.1
|
||||
- release-2.2
|
||||
|
||||
install:
|
||||
- npm uninstall typescript
|
||||
|
||||
+35
@@ -10,15 +10,19 @@ TypeScript is authored by:
|
||||
* Alexander Rusakov
|
||||
* Ali Sabzevari
|
||||
* Aliaksandr Radzivanovich
|
||||
* Aluan Haddad
|
||||
* Anatoly Ressin
|
||||
* Anders Hejlsberg
|
||||
* Andreas Martin
|
||||
* Andrej Baran
|
||||
* Andrew Ochsner
|
||||
* Andrew Z Allen
|
||||
* András Parditka
|
||||
* Andy Hanson
|
||||
* Anil Anar
|
||||
* Anton Khlynovskiy
|
||||
* Anton Tolmachev
|
||||
* Anubha Mathur
|
||||
* Arnav Singh
|
||||
* Arthur Ozga
|
||||
* Asad Saeeduddin
|
||||
@@ -26,6 +30,7 @@ TypeScript is authored by:
|
||||
* Basarat Ali Syed
|
||||
* Ben Duffield
|
||||
* Ben Mosher
|
||||
* Benjamin Bock
|
||||
* Bill Ticehurst
|
||||
* Blake Embrey
|
||||
* @bootstraponline
|
||||
@@ -33,6 +38,7 @@ TypeScript is authored by:
|
||||
* Brett Mayen
|
||||
* Bryan Forbes
|
||||
* Caitlin Potter
|
||||
* @cedvdb
|
||||
* Charly POLY
|
||||
* Chris Bubernak
|
||||
* Christophe Vidal
|
||||
@@ -42,12 +48,15 @@ TypeScript is authored by:
|
||||
* Cotton Hou
|
||||
* Cyrus Najmabadi
|
||||
* Dafrok Zhang
|
||||
* Dahan Gong
|
||||
* Dan Corder
|
||||
* Dan Quirk
|
||||
* Daniel Hollocher
|
||||
* Daniel Lehenbauer
|
||||
* Daniel Rosenwasser
|
||||
* David Kmenta
|
||||
* David Li
|
||||
* David Sheldrick
|
||||
* David Souther
|
||||
* Denis Nedelyaev
|
||||
* Dick van den Brink
|
||||
@@ -55,10 +64,12 @@ TypeScript is authored by:
|
||||
* Dirk Holtwick
|
||||
* Dom Chen
|
||||
* Doug Ilijev
|
||||
* @e-cloud
|
||||
* Elisée Maurer
|
||||
* Emilio García-Pumarino
|
||||
* Eric Tsang
|
||||
* Erik Edrosa
|
||||
* Erik McClenney
|
||||
* Ethan Resnick
|
||||
* Ethan Rubio
|
||||
* Evan Martin
|
||||
@@ -66,6 +77,7 @@ TypeScript is authored by:
|
||||
* Eyas Sharaiha
|
||||
* Fabian Cook
|
||||
* @falsandtru
|
||||
* @flowmemo
|
||||
* Frank Wallis
|
||||
* Franklin Tse
|
||||
* František Žiacik
|
||||
@@ -78,14 +90,20 @@ TypeScript is authored by:
|
||||
* Guillaume Salles
|
||||
* Guy Bedford
|
||||
* Harald Niesche
|
||||
* Hendrik Liebau
|
||||
* Herrington Darkholme
|
||||
* Homa Wong
|
||||
* Iain Monro
|
||||
* Igor Novozhilov
|
||||
* Ingvar Stepanyan
|
||||
* Isiah Meadows
|
||||
* Ivo Gabe de Wolff
|
||||
* Iwata Hidetaka
|
||||
* Jakub Młokosiewicz
|
||||
* James Henry
|
||||
* James Whitney
|
||||
* Jason Freeman
|
||||
* Jason Jarrett
|
||||
* Jason Killian
|
||||
* Jason Ramsay
|
||||
* JBerger
|
||||
@@ -93,6 +111,7 @@ TypeScript is authored by:
|
||||
* Jeffrey Morlan
|
||||
* Jesse Schalken
|
||||
* Jiri Tobisek
|
||||
* Joel Day
|
||||
* Joey Wilson
|
||||
* Johannes Rieken
|
||||
* John Vilk
|
||||
@@ -102,26 +121,34 @@ TypeScript is authored by:
|
||||
* Jonathan Turner
|
||||
* Jonathon Smith
|
||||
* Josh Abernathy
|
||||
* Josh Goldberg
|
||||
* Josh Kalderimis
|
||||
* Josh Soref
|
||||
* Juan Luis Boya García
|
||||
* Julian Williams
|
||||
* Justin Bay
|
||||
* Justin Johansson
|
||||
* K. Preißer
|
||||
* Kagami Sascha Rosylight
|
||||
* Kanchalai Tanglertsampan
|
||||
* Keith Mashinter
|
||||
* Ken Howard
|
||||
* Kenji Imamula
|
||||
* Kevin Lang
|
||||
* Kitson Kelly
|
||||
* Klaus Meinhardt
|
||||
* Kyle Kelley
|
||||
* Kārlis Gaņģis
|
||||
* Lorant Pinter
|
||||
* Lucien Greathouse
|
||||
* Lukas Elmer
|
||||
* Magnus Hiie
|
||||
* Manish Giri
|
||||
* Marin Marinov
|
||||
* Marius Schulz
|
||||
* Martin Vseticka
|
||||
* Masahiro Wakame
|
||||
* Matt Bierner
|
||||
* Matt McCutchen
|
||||
* Mattias Buelens
|
||||
* Mattias Buelens
|
||||
@@ -129,8 +156,11 @@ TypeScript is authored by:
|
||||
* Micah Zoltu
|
||||
* Michael
|
||||
* Michael Bromley
|
||||
* Mike Busyrev
|
||||
* Mine Starks
|
||||
* Mohamed Hegazy
|
||||
* Myles Megyesi
|
||||
* Natalie Coley
|
||||
* Nathan Shively-Sanders
|
||||
* Nathan Yee
|
||||
* Nicolas Henry
|
||||
@@ -155,6 +185,8 @@ TypeScript is authored by:
|
||||
* @progre
|
||||
* Punya Biswal
|
||||
* Rado Kirov
|
||||
* Raj Dosanjh
|
||||
* Richard Karmazín
|
||||
* Richard Knoll
|
||||
* Richard Sentino
|
||||
* Robert Coie
|
||||
@@ -166,6 +198,7 @@ TypeScript is authored by:
|
||||
* Ryohei Ikegami
|
||||
* Sam El-Husseini
|
||||
* Sarangan Rajamanickam
|
||||
* Sergey Rubanov
|
||||
* Sergey Shandar
|
||||
* Sheetal Nandi
|
||||
* Shengping Zhong
|
||||
@@ -173,6 +206,7 @@ TypeScript is authored by:
|
||||
* Simon Hürlimann
|
||||
* Slawomir Sadziak
|
||||
* Solal Pirelli
|
||||
* Soo Jae Hwang
|
||||
* Stan Thomas
|
||||
* Stanislav Sysoev
|
||||
* Steve Lucco
|
||||
@@ -192,6 +226,7 @@ TypeScript is authored by:
|
||||
* Tomas Grubliauskas
|
||||
* Torben Fitschen
|
||||
* TruongSinh Tran-Nguyen
|
||||
* Vadi Taslim
|
||||
* Vidar Tonaas Fauske
|
||||
* Viktor Zozulyak
|
||||
* Vilic Vane
|
||||
|
||||
+78
-85
@@ -2,6 +2,7 @@
|
||||
import * as cp from "child_process";
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
import child_process = require("child_process");
|
||||
import originalGulp = require("gulp");
|
||||
import helpMaker = require("gulp-help");
|
||||
import runSequence = require("run-sequence");
|
||||
@@ -21,10 +22,6 @@ declare module "gulp-typescript" {
|
||||
import * as insert from "gulp-insert";
|
||||
import * as sourcemaps from "gulp-sourcemaps";
|
||||
import Q = require("q");
|
||||
declare global {
|
||||
// `del` further depends on `Promise` (and is also not included), so we just, patch the global scope's Promise to Q's (which we already include in our deps because gulp depends on it)
|
||||
type Promise<T> = Q.Promise<T>;
|
||||
}
|
||||
import del = require("del");
|
||||
import mkdirP = require("mkdirp");
|
||||
import minimist = require("minimist");
|
||||
@@ -41,21 +38,24 @@ const {runTestsInParallel} = mochaParallel;
|
||||
Error.stackTraceLimit = 1000;
|
||||
|
||||
const cmdLineOptions = minimist(process.argv.slice(2), {
|
||||
boolean: ["debug", "light", "colors", "lint", "soft"],
|
||||
boolean: ["debug", "inspect", "light", "colors", "lint", "soft"],
|
||||
string: ["browser", "tests", "host", "reporter", "stackTraceLimit"],
|
||||
alias: {
|
||||
b: "browser",
|
||||
d: "debug",
|
||||
t: "tests",
|
||||
test: "tests",
|
||||
r: "reporter",
|
||||
color: "colors",
|
||||
f: "files",
|
||||
file: "files"
|
||||
file: "files",
|
||||
w: "workers",
|
||||
},
|
||||
default: {
|
||||
soft: false,
|
||||
colors: process.env.colors || process.env.color || true,
|
||||
debug: process.env.debug || process.env.d,
|
||||
inspect: process.env.inspect,
|
||||
host: process.env.TYPESCRIPT_HOST || process.env.host || "node",
|
||||
browser: process.env.browser || process.env.b || "IE",
|
||||
tests: process.env.test || process.env.tests || process.env.t,
|
||||
@@ -63,6 +63,7 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
|
||||
reporter: process.env.reporter || process.env.r,
|
||||
lint: process.env.lint || true,
|
||||
files: process.env.f || process.env.file || process.env.files || "",
|
||||
workers: process.env.workerCount || os.cpus().length,
|
||||
}
|
||||
});
|
||||
|
||||
@@ -136,6 +137,14 @@ const es2017LibrarySourceMap = es2017LibrarySource.map(function(source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
const esnextLibrarySource = [
|
||||
"esnext.asynciterable.d.ts"
|
||||
];
|
||||
|
||||
const esnextLibrarySourceMap = esnextLibrarySource.map(function (source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
const hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];
|
||||
|
||||
const librarySourceMap = [
|
||||
@@ -150,11 +159,15 @@ const librarySourceMap = [
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
{ target: "lib.esnext.d.ts", sources: ["header.d.ts", "esnext.d.ts"] },
|
||||
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap);
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") },
|
||||
{ target: "lib.es2016.full.d.ts", sources: ["header.d.ts", "es2016.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") },
|
||||
{ target: "lib.es2017.full.d.ts", sources: ["header.d.ts", "es2017.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") },
|
||||
{ target: "lib.esnext.full.d.ts", sources: ["header.d.ts", "esnext.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") },
|
||||
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap, esnextLibrarySourceMap);
|
||||
|
||||
const libraryTargets = librarySourceMap.map(function(f) {
|
||||
return path.join(builtLocalDirectory, f.target);
|
||||
@@ -166,7 +179,7 @@ for (const i in libraryTargets) {
|
||||
const sources = [copyright].concat(entry.sources.map(function(s) {
|
||||
return path.join(libraryDirectory, s);
|
||||
}));
|
||||
gulp.task(target, false, [], function() {
|
||||
gulp.task(target, /*help*/ false, [], function() {
|
||||
return gulp.src(sources)
|
||||
.pipe(newer(target))
|
||||
.pipe(concat(target, { newLine: "\n\n" }))
|
||||
@@ -266,7 +279,7 @@ function getCompilerSettings(base: tsc.Settings, useBuiltCompiler?: boolean): ts
|
||||
return copy;
|
||||
}
|
||||
|
||||
gulp.task(configureNightlyJs, false, [], () => {
|
||||
gulp.task(configureNightlyJs, /*help*/ false, [], () => {
|
||||
const settings: tsc.Settings = {
|
||||
declaration: false,
|
||||
removeComments: true,
|
||||
@@ -295,7 +308,7 @@ const importDefinitelyTypedTestsDirectory = path.join(scriptsDirectory, "importD
|
||||
const importDefinitelyTypedTestsJs = path.join(importDefinitelyTypedTestsDirectory, "importDefinitelyTypedTests.js");
|
||||
const importDefinitelyTypedTestsTs = path.join(importDefinitelyTypedTestsDirectory, "importDefinitelyTypedTests.ts");
|
||||
|
||||
gulp.task(importDefinitelyTypedTestsJs, false, [], () => {
|
||||
gulp.task(importDefinitelyTypedTestsJs, /*help*/ false, [], () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({
|
||||
declaration: false,
|
||||
removeComments: true,
|
||||
@@ -326,7 +339,7 @@ const generatedDiagnosticMessagesJSON = path.join(compilerDirectory, "diagnostic
|
||||
const builtGeneratedDiagnosticMessagesJSON = path.join(builtLocalDirectory, "diagnosticMessages.generated.json");
|
||||
|
||||
// processDiagnosticMessages script
|
||||
gulp.task(processDiagnosticMessagesJs, false, [], () => {
|
||||
gulp.task(processDiagnosticMessagesJs, /*help*/ false, [], () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({
|
||||
target: "es5",
|
||||
declaration: false,
|
||||
@@ -374,26 +387,26 @@ function prependCopyright(outputCopyright: boolean = !useDebugMode) {
|
||||
return insert.prepend(outputCopyright ? (copyrightContent || (copyrightContent = fs.readFileSync(copyright).toString())) : "");
|
||||
}
|
||||
|
||||
gulp.task(builtLocalCompiler, false, [servicesFile], () => {
|
||||
const localCompilerProject = tsc.createProject("src/compiler/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/true));
|
||||
gulp.task(builtLocalCompiler, /*help*/ false, [servicesFile], () => {
|
||||
const localCompilerProject = tsc.createProject("src/compiler/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ true));
|
||||
return localCompilerProject.src()
|
||||
.pipe(newer(builtLocalCompiler))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(localCompilerProject())
|
||||
.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest("."));
|
||||
.pipe(gulp.dest("src/compiler"));
|
||||
});
|
||||
|
||||
gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => {
|
||||
const servicesProject = tsc.createProject("src/services/tsconfig.json", getCompilerSettings({ removeComments: false }, /*useBuiltCompiler*/false));
|
||||
gulp.task(servicesFile, /*help*/ false, ["lib", "generate-diagnostics"], () => {
|
||||
const servicesProject = tsc.createProject("src/services/tsconfig.json", getCompilerSettings({ removeComments: false }, /*useBuiltCompiler*/ false));
|
||||
const {js, dts} = servicesProject.src()
|
||||
.pipe(newer(servicesFile))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(servicesProject());
|
||||
const completedJs = js.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."));
|
||||
const completedDts = dts.pipe(prependCopyright(/*outputCopyright*/true))
|
||||
const completedDts = dts.pipe(prependCopyright(/*outputCopyright*/ true))
|
||||
.pipe(insert.transform((contents, file) => {
|
||||
file.path = standaloneDefinitionsFile;
|
||||
return contents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, "$1$2enum $3 {$4");
|
||||
@@ -408,19 +421,19 @@ gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => {
|
||||
file.path = nodeDefinitionsFile;
|
||||
return content + "\r\nexport = ts;";
|
||||
}))
|
||||
.pipe(gulp.dest(".")),
|
||||
.pipe(gulp.dest("src/services")),
|
||||
completedDts.pipe(clone())
|
||||
.pipe(insert.transform((content, file) => {
|
||||
file.path = nodeStandaloneDefinitionsFile;
|
||||
return content.replace(/declare (namespace|module) ts/g, 'declare module "typescript"');
|
||||
}))
|
||||
]).pipe(gulp.dest("."));
|
||||
]).pipe(gulp.dest("src/services"));
|
||||
});
|
||||
|
||||
// cancellationToken.js
|
||||
const cancellationTokenJs = path.join(builtLocalDirectory, "cancellationToken.js");
|
||||
gulp.task(cancellationTokenJs, false, [servicesFile], () => {
|
||||
const cancellationTokenProject = tsc.createProject("src/server/cancellationToken/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/true));
|
||||
gulp.task(cancellationTokenJs, /*help*/ false, [servicesFile], () => {
|
||||
const cancellationTokenProject = tsc.createProject("src/server/cancellationToken/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ true));
|
||||
return cancellationTokenProject.src()
|
||||
.pipe(newer(cancellationTokenJs))
|
||||
.pipe(sourcemaps.init())
|
||||
@@ -432,34 +445,34 @@ gulp.task(cancellationTokenJs, false, [servicesFile], () => {
|
||||
|
||||
// typingsInstallerFile.js
|
||||
const typingsInstallerJs = path.join(builtLocalDirectory, "typingsInstaller.js");
|
||||
gulp.task(typingsInstallerJs, false, [servicesFile], () => {
|
||||
const cancellationTokenProject = tsc.createProject("src/server/typingsInstaller/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/true));
|
||||
gulp.task(typingsInstallerJs, /*help*/ false, [servicesFile], () => {
|
||||
const cancellationTokenProject = tsc.createProject("src/server/typingsInstaller/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ true));
|
||||
return cancellationTokenProject.src()
|
||||
.pipe(newer(typingsInstallerJs))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(cancellationTokenProject())
|
||||
.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest("."));
|
||||
.pipe(gulp.dest("src/server/typingsInstaller"));
|
||||
});
|
||||
|
||||
const serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
|
||||
gulp.task(serverFile, false, [servicesFile, typingsInstallerJs, cancellationTokenJs], () => {
|
||||
const serverProject = tsc.createProject("src/server/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/true));
|
||||
gulp.task(serverFile, /*help*/ false, [servicesFile, typingsInstallerJs, cancellationTokenJs], () => {
|
||||
const serverProject = tsc.createProject("src/server/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ true));
|
||||
return serverProject.src()
|
||||
.pipe(newer(serverFile))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(serverProject())
|
||||
.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest("."));
|
||||
.pipe(gulp.dest("src/server"));
|
||||
});
|
||||
|
||||
const tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
|
||||
const tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts");
|
||||
|
||||
gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => {
|
||||
gulp.task(tsserverLibraryFile, /*help*/ false, [servicesFile], (done) => {
|
||||
const serverLibraryProject = tsc.createProject("src/server/tsconfig.library.json", getCompilerSettings({}, /*useBuiltCompiler*/ true));
|
||||
const {js, dts}: { js: NodeJS.ReadableStream, dts: NodeJS.ReadableStream } = serverLibraryProject.src()
|
||||
.pipe(sourcemaps.init())
|
||||
@@ -469,12 +482,12 @@ gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => {
|
||||
return merge2([
|
||||
js.pipe(prependCopyright())
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest(".")),
|
||||
dts.pipe(prependCopyright(/*outputCopyright*/true))
|
||||
.pipe(gulp.dest("src/server")),
|
||||
dts.pipe(prependCopyright(/*outputCopyright*/ true))
|
||||
.pipe(insert.transform((content) => {
|
||||
return content + "\r\nexport = ts;\r\nexport as namespace ts;";
|
||||
}))
|
||||
.pipe(gulp.dest("."))
|
||||
.pipe(gulp.dest("src/server"))
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -488,7 +501,7 @@ const word2mdTs = path.join(scriptsDirectory, "word2md.ts");
|
||||
const specWord = path.join(docDirectory, "TypeScript Language Specification.docx");
|
||||
const specMd = path.join(docDirectory, "spec.md");
|
||||
|
||||
gulp.task(word2mdJs, false, [], () => {
|
||||
gulp.task(word2mdJs, /*help*/ false, [], () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({
|
||||
outFile: word2mdJs
|
||||
}, /*useBuiltCompiler*/ false);
|
||||
@@ -500,7 +513,7 @@ gulp.task(word2mdJs, false, [], () => {
|
||||
.pipe(gulp.dest("."));
|
||||
});
|
||||
|
||||
gulp.task(specMd, false, [word2mdJs], (done) => {
|
||||
gulp.task(specMd, /*help*/ false, [word2mdJs], (done) => {
|
||||
const specWordFullPath = path.resolve(specWord);
|
||||
const specMDFullPath = path.resolve(specMd);
|
||||
const cmd = "cscript //nologo " + word2mdJs + " \"" + specWordFullPath + "\" " + "\"" + specMDFullPath + "\"";
|
||||
@@ -516,10 +529,10 @@ gulp.task("clean", "Cleans the compiler output, declare files, and tests", [], (
|
||||
return del([builtDirectory]);
|
||||
});
|
||||
|
||||
gulp.task("useDebugMode", false, [], (done) => { useDebugMode = true; done(); });
|
||||
gulp.task("dontUseDebugMode", false, [], (done) => { useDebugMode = false; done(); });
|
||||
gulp.task("useDebugMode", /*help*/ false, [], (done) => { useDebugMode = true; done(); });
|
||||
gulp.task("dontUseDebugMode", /*help*/ false, [], (done) => { useDebugMode = false; done(); });
|
||||
|
||||
gulp.task("VerifyLKG", false, [], () => {
|
||||
gulp.task("VerifyLKG", /*help*/ false, [], () => {
|
||||
const expectedFiles = [builtLocalCompiler, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, typingsInstallerJs, cancellationTokenJs].concat(libraryTargets);
|
||||
const missingFiles = expectedFiles.filter(function(f) {
|
||||
return !fs.existsSync(f);
|
||||
@@ -532,7 +545,7 @@ gulp.task("VerifyLKG", false, [], () => {
|
||||
return gulp.src(expectedFiles).pipe(gulp.dest(LKGDirectory));
|
||||
});
|
||||
|
||||
gulp.task("LKGInternal", false, ["lib", "local"]);
|
||||
gulp.task("LKGInternal", /*help*/ false, ["lib", "local"]);
|
||||
|
||||
gulp.task("LKG", "Makes a new LKG out of the built js files", ["clean", "dontUseDebugMode"], () => {
|
||||
return runSequence("LKGInternal", "VerifyLKG");
|
||||
@@ -541,14 +554,14 @@ gulp.task("LKG", "Makes a new LKG out of the built js files", ["clean", "dontUse
|
||||
|
||||
// Task to build the tests infrastructure using the built compiler
|
||||
const run = path.join(builtLocalDirectory, "run.js");
|
||||
gulp.task(run, false, [servicesFile], () => {
|
||||
const testProject = tsc.createProject("src/harness/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/true));
|
||||
gulp.task(run, /*help*/ false, [servicesFile], () => {
|
||||
const testProject = tsc.createProject("src/harness/tsconfig.json", getCompilerSettings({}, /*useBuiltCompiler*/ true));
|
||||
return testProject.src()
|
||||
.pipe(newer(run))
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(testProject())
|
||||
.pipe(sourcemaps.write(".", { includeContent: false, sourceRoot: "../../" }))
|
||||
.pipe(gulp.dest("."));
|
||||
.pipe(gulp.dest("src/harness"));
|
||||
});
|
||||
|
||||
const internalTests = "internal/";
|
||||
@@ -586,6 +599,7 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
|
||||
cleanTestDirs((err) => {
|
||||
if (err) { console.error(err); failWithStatus(err, 1); }
|
||||
const debug = cmdLineOptions["debug"];
|
||||
const inspect = cmdLineOptions["inspect"];
|
||||
const tests = cmdLineOptions["tests"];
|
||||
const light = cmdLineOptions["light"];
|
||||
const stackTraceLimit = cmdLineOptions["stackTraceLimit"];
|
||||
@@ -604,7 +618,7 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
|
||||
} while (fs.existsSync(taskConfigsFolder));
|
||||
fs.mkdirSync(taskConfigsFolder);
|
||||
|
||||
workerCount = process.env.workerCount || os.cpus().length;
|
||||
workerCount = cmdLineOptions["workers"];
|
||||
}
|
||||
|
||||
if (tests || light || taskConfigsFolder) {
|
||||
@@ -622,7 +636,10 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
|
||||
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
|
||||
if (!runInParallel) {
|
||||
const args = [];
|
||||
if (debug) {
|
||||
if (inspect) {
|
||||
args.push("--inspect");
|
||||
}
|
||||
if (inspect || debug) {
|
||||
args.push("--debug-brk");
|
||||
}
|
||||
args.push("-R", reporter);
|
||||
@@ -711,7 +728,7 @@ gulp.task("runtests",
|
||||
|
||||
const nodeServerOutFile = "tests/webTestServer.js";
|
||||
const nodeServerInFile = "tests/webTestServer.ts";
|
||||
gulp.task(nodeServerOutFile, false, [servicesFile], () => {
|
||||
gulp.task(nodeServerOutFile, /*help*/ false, [servicesFile], () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({ module: "commonjs" }, /*useBuiltCompiler*/ true);
|
||||
return gulp.src(nodeServerInFile)
|
||||
.pipe(newer(nodeServerOutFile))
|
||||
@@ -737,14 +754,14 @@ gulp.task("browserify", "Runs browserify on run.js to produce a file suitable fo
|
||||
const originalMap = file.sourceMap;
|
||||
const prebundledContent = file.contents.toString();
|
||||
// Make paths absolute to help sorcery deal with all the terrible paths being thrown around
|
||||
originalMap.sources = originalMap.sources.map(s => path.resolve(s));
|
||||
originalMap.sources = originalMap.sources.map(s => path.resolve(path.join("src/harness", s)));
|
||||
// intoStream (below) makes browserify think the input file is named this, so this is what it puts in the sourcemap
|
||||
originalMap.file = "built/local/_stream_0.js";
|
||||
|
||||
browserify(intoStream(file.contents), { debug: true })
|
||||
.bundle((err, res) => {
|
||||
// assumes file.contents is a Buffer
|
||||
const maps = JSON.parse(convertMap.fromSource(res.toString(), /*largeSource*/true).toJSON());
|
||||
const maps = JSON.parse(convertMap.fromSource(res.toString(), /*largeSource*/ true).toJSON());
|
||||
delete maps.sourceRoot;
|
||||
maps.sources = maps.sources.map(s => path.resolve(s === "_stream_0.js" ? "built/local/_stream_0.js" : s));
|
||||
// Strip browserify's inline comments away (could probably just let sorcery do this, but then we couldn't fix the paths)
|
||||
@@ -762,11 +779,11 @@ gulp.task("browserify", "Runs browserify on run.js to produce a file suitable fo
|
||||
});
|
||||
const finalMap = chain.apply();
|
||||
file.sourceMap = finalMap;
|
||||
next(undefined, file);
|
||||
next(/*err*/ undefined, file);
|
||||
});
|
||||
}))
|
||||
.pipe(sourcemaps.write(".", { includeContent: false }))
|
||||
.pipe(gulp.dest("."));
|
||||
.pipe(gulp.dest("src/harness"));
|
||||
});
|
||||
|
||||
|
||||
@@ -876,7 +893,7 @@ gulp.task("baseline-accept-test262", "Makes the most recent test262 test results
|
||||
// Webhost
|
||||
const webhostPath = "tests/webhost/webtsc.ts";
|
||||
const webhostJsPath = "tests/webhost/webtsc.js";
|
||||
gulp.task(webhostJsPath, false, [servicesFile], () => {
|
||||
gulp.task(webhostJsPath, /*help*/ false, [servicesFile], () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({
|
||||
outFile: webhostJsPath
|
||||
}, /*useBuiltCompiler*/ true);
|
||||
@@ -896,7 +913,7 @@ gulp.task("webhost", "Builds the tsc web host", [webhostJsPath], () => {
|
||||
// Perf compiler
|
||||
const perftscPath = "tests/perftsc.ts";
|
||||
const perftscJsPath = "built/local/perftsc.js";
|
||||
gulp.task(perftscJsPath, false, [servicesFile], () => {
|
||||
gulp.task(perftscJsPath, /*help*/ false, [servicesFile], () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({
|
||||
outFile: perftscJsPath
|
||||
}, /*useBuiltCompiler*/ true);
|
||||
@@ -914,10 +931,10 @@ gulp.task("perftsc", "Builds augmented version of the compiler for perf tests",
|
||||
// Instrumented compiler
|
||||
const loggedIOpath = path.join(harnessDirectory, "loggedIO.ts");
|
||||
const loggedIOJsPath = path.join(builtLocalDirectory, "loggedIO.js");
|
||||
gulp.task(loggedIOJsPath, false, [], (done) => {
|
||||
gulp.task(loggedIOJsPath, /*help*/ false, [], (done) => {
|
||||
const temp = path.join(builtLocalDirectory, "temp");
|
||||
mkdirP(temp, (err) => {
|
||||
if (err) { console.error(err); done(err); process.exit(1); };
|
||||
if (err) { console.error(err); done(err); process.exit(1); }
|
||||
exec(host, [LKGCompiler, "--types --outdir", temp, loggedIOpath], () => {
|
||||
fs.renameSync(path.join(temp, "/harness/loggedIO.js"), loggedIOJsPath);
|
||||
del(temp).then(() => done(), done);
|
||||
@@ -927,7 +944,7 @@ gulp.task(loggedIOJsPath, false, [], (done) => {
|
||||
|
||||
const instrumenterPath = path.join(harnessDirectory, "instrumenter.ts");
|
||||
const instrumenterJsPath = path.join(builtLocalDirectory, "instrumenter.js");
|
||||
gulp.task(instrumenterJsPath, false, [servicesFile], () => {
|
||||
gulp.task(instrumenterJsPath, /*help*/ false, [servicesFile], () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({
|
||||
outFile: instrumenterJsPath
|
||||
}, /*useBuiltCompiler*/ true);
|
||||
@@ -948,7 +965,7 @@ gulp.task("update-sublime", "Updates the sublime plugin's tsserver", ["local", s
|
||||
});
|
||||
|
||||
gulp.task("build-rules", "Compiles tslint rules to js", () => {
|
||||
const settings: tsc.Settings = getCompilerSettings({ module: "commonjs" }, /*useBuiltCompiler*/ false);
|
||||
const settings: tsc.Settings = getCompilerSettings({ module: "commonjs", "lib": ["es6"] }, /*useBuiltCompiler*/ false);
|
||||
const dest = path.join(builtLocalDirectory, "tslint");
|
||||
return gulp.src("scripts/tslint/**/*.ts")
|
||||
.pipe(newer({
|
||||
@@ -1007,40 +1024,16 @@ function spawnLintWorker(files: {path: string}[], callback: (failures: number) =
|
||||
}
|
||||
|
||||
gulp.task("lint", "Runs tslint on the compiler sources. Optional arguments are: --f[iles]=regex", ["build-rules"], () => {
|
||||
const fileMatcher = RegExp(cmdLineOptions["files"]);
|
||||
if (fold.isTravis()) console.log(fold.start("lint"));
|
||||
|
||||
let files: {stat: fs.Stats, path: string}[] = [];
|
||||
return gulp.src(lintTargets, { read: false })
|
||||
.pipe(through2.obj((chunk, enc, cb) => {
|
||||
files.push(chunk);
|
||||
cb();
|
||||
}, (cb) => {
|
||||
files = files.filter(file => fileMatcher.test(file.path)).sort((filea, fileb) => filea.stat.size - fileb.stat.size);
|
||||
const workerCount = (process.env.workerCount && +process.env.workerCount) || os.cpus().length;
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
spawnLintWorker(files, finished);
|
||||
}
|
||||
|
||||
let completed = 0;
|
||||
let failures = 0;
|
||||
function finished(fails) {
|
||||
completed++;
|
||||
failures += fails;
|
||||
if (completed === workerCount) {
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
if (failures > 0) {
|
||||
throw new Error(`Linter errors: ${failures}`);
|
||||
}
|
||||
else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
const fileMatcher = cmdLineOptions["files"];
|
||||
const files = fileMatcher
|
||||
? `src/**/${fileMatcher}`
|
||||
: "Gulpfile.ts 'scripts/tslint/*.ts' 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts'";
|
||||
const cmd = `node node_modules/tslint/bin/tslint ${files} --format stylish`;
|
||||
console.log("Linting: " + cmd);
|
||||
child_process.execSync(cmd, { stdio: [0, 1, 2] });
|
||||
});
|
||||
|
||||
|
||||
gulp.task("default", "Runs 'local'", ["local"]);
|
||||
|
||||
gulp.task("watch", "Watches the src/ directory for changes and executes runtests-parallel.", [], () => {
|
||||
|
||||
+146
-250
@@ -6,13 +6,12 @@ var path = require("path");
|
||||
var child_process = require("child_process");
|
||||
var fold = require("travis-fold");
|
||||
var runTestsInParallel = require("./scripts/mocha-parallel").runTestsInParallel;
|
||||
var ts = require("./lib/typescript");
|
||||
|
||||
|
||||
// Variables
|
||||
var compilerDirectory = "src/compiler/";
|
||||
var servicesDirectory = "src/services/";
|
||||
var serverDirectory = "src/server/";
|
||||
var typingsInstallerDirectory = "src/server/typingsInstaller";
|
||||
var cancellationTokenDirectory = "src/server/cancellationToken";
|
||||
var harnessDirectory = "src/harness/";
|
||||
var libraryDirectory = "src/lib/";
|
||||
var scriptsDirectory = "scripts/";
|
||||
@@ -30,10 +29,29 @@ var thirdParty = "ThirdPartyNoticeText.txt";
|
||||
var nodeModulesPathPrefix = path.resolve("./node_modules/.bin/") + path.delimiter;
|
||||
if (process.env.path !== undefined) {
|
||||
process.env.path = nodeModulesPathPrefix + process.env.path;
|
||||
} else if (process.env.PATH !== undefined) {
|
||||
}
|
||||
else if (process.env.PATH !== undefined) {
|
||||
process.env.PATH = nodeModulesPathPrefix + process.env.PATH;
|
||||
}
|
||||
|
||||
function filesFromConfig(configPath) {
|
||||
var configText = fs.readFileSync(configPath).toString();
|
||||
var config = ts.parseConfigFileTextToJson(configPath, configText, /*stripComments*/ true);
|
||||
if (config.error) {
|
||||
throw new Error(diagnosticsToString([config.error]));
|
||||
}
|
||||
const configFileContent = ts.parseJsonConfigFileContent(config.config, ts.sys, path.dirname(configPath));
|
||||
if (configFileContent.errors && configFileContent.errors.length) {
|
||||
throw new Error(diagnosticsToString(configFileContent.errors));
|
||||
}
|
||||
|
||||
return configFileContent.fileNames;
|
||||
|
||||
function diagnosticsToString(s) {
|
||||
return s.map(function(e) { return ts.flattenDiagnosticMessageText(e.messageText, ts.sys.newLine); }).join(ts.sys.newLine);
|
||||
}
|
||||
}
|
||||
|
||||
function toNs(diff) {
|
||||
return diff[0] * 1e9 + diff[1];
|
||||
}
|
||||
@@ -56,173 +74,13 @@ function measure(marker) {
|
||||
console.log("travis_time:end:" + marker.id + ":start=" + toNs(marker.stamp) + ",finish=" + toNs(total) + ",duration=" + toNs(diff) + "\r");
|
||||
}
|
||||
|
||||
var compilerSources = [
|
||||
"core.ts",
|
||||
"performance.ts",
|
||||
"sys.ts",
|
||||
"types.ts",
|
||||
"scanner.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"checker.ts",
|
||||
"factory.ts",
|
||||
"visitor.ts",
|
||||
"transformers/destructuring.ts",
|
||||
"transformers/ts.ts",
|
||||
"transformers/jsx.ts",
|
||||
"transformers/esnext.ts",
|
||||
"transformers/es2017.ts",
|
||||
"transformers/es2016.ts",
|
||||
"transformers/es2015.ts",
|
||||
"transformers/generators.ts",
|
||||
"transformers/es5.ts",
|
||||
"transformers/module/es2015.ts",
|
||||
"transformers/module/system.ts",
|
||||
"transformers/module/module.ts",
|
||||
"transformer.ts",
|
||||
"sourcemap.ts",
|
||||
"comments.ts",
|
||||
"declarationEmitter.ts",
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
"tsc.ts",
|
||||
"diagnosticInformationMap.generated.ts"
|
||||
].map(function (f) {
|
||||
return path.join(compilerDirectory, f);
|
||||
});
|
||||
|
||||
var servicesSources = [
|
||||
"core.ts",
|
||||
"performance.ts",
|
||||
"sys.ts",
|
||||
"types.ts",
|
||||
"scanner.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"checker.ts",
|
||||
"factory.ts",
|
||||
"visitor.ts",
|
||||
"transformers/destructuring.ts",
|
||||
"transformers/ts.ts",
|
||||
"transformers/jsx.ts",
|
||||
"transformers/esnext.ts",
|
||||
"transformers/es2017.ts",
|
||||
"transformers/es2016.ts",
|
||||
"transformers/es2015.ts",
|
||||
"transformers/generators.ts",
|
||||
"transformers/es5.ts",
|
||||
"transformers/module/es2015.ts",
|
||||
"transformers/module/system.ts",
|
||||
"transformers/module/module.ts",
|
||||
"transformer.ts",
|
||||
"sourcemap.ts",
|
||||
"comments.ts",
|
||||
"declarationEmitter.ts",
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
"diagnosticInformationMap.generated.ts"
|
||||
].map(function (f) {
|
||||
return path.join(compilerDirectory, f);
|
||||
}).concat([
|
||||
"types.ts",
|
||||
"utilities.ts",
|
||||
"breakpoints.ts",
|
||||
"classifier.ts",
|
||||
"completions.ts",
|
||||
"documentHighlights.ts",
|
||||
"documentRegistry.ts",
|
||||
"findAllReferences.ts",
|
||||
"goToDefinition.ts",
|
||||
"goToImplementation.ts",
|
||||
"jsDoc.ts",
|
||||
"jsTyping.ts",
|
||||
"navigateTo.ts",
|
||||
"navigationBar.ts",
|
||||
"outliningElementsCollector.ts",
|
||||
"patternMatcher.ts",
|
||||
"preProcess.ts",
|
||||
"rename.ts",
|
||||
"services.ts",
|
||||
"shims.ts",
|
||||
"signatureHelp.ts",
|
||||
"symbolDisplay.ts",
|
||||
"transpile.ts",
|
||||
// Formatting
|
||||
"formatting/formatting.ts",
|
||||
"formatting/formattingContext.ts",
|
||||
"formatting/formattingRequestKind.ts",
|
||||
"formatting/formattingScanner.ts",
|
||||
"formatting/references.ts",
|
||||
"formatting/rule.ts",
|
||||
"formatting/ruleAction.ts",
|
||||
"formatting/ruleDescriptor.ts",
|
||||
"formatting/ruleFlag.ts",
|
||||
"formatting/ruleOperation.ts",
|
||||
"formatting/ruleOperationContext.ts",
|
||||
"formatting/rules.ts",
|
||||
"formatting/rulesMap.ts",
|
||||
"formatting/rulesProvider.ts",
|
||||
"formatting/smartIndenter.ts",
|
||||
"formatting/tokenRange.ts",
|
||||
// CodeFixes
|
||||
"codeFixProvider.ts",
|
||||
"codefixes/fixes.ts",
|
||||
"codefixes/fixExtendsInterfaceBecomesImplements.ts",
|
||||
"codefixes/fixClassIncorrectlyImplementsInterface.ts",
|
||||
"codefixes/fixClassDoesntImplementInheritedAbstractMember.ts",
|
||||
"codefixes/fixClassSuperMustPrecedeThisAccess.ts",
|
||||
"codefixes/fixConstructorForDerivedNeedSuperCall.ts",
|
||||
"codefixes/helpers.ts",
|
||||
"codefixes/importFixes.ts",
|
||||
"codefixes/unusedIdentifierFixes.ts"
|
||||
].map(function (f) {
|
||||
return path.join(servicesDirectory, f);
|
||||
}));
|
||||
|
||||
var baseServerCoreSources = [
|
||||
"builder.ts",
|
||||
"editorServices.ts",
|
||||
"lsHost.ts",
|
||||
"project.ts",
|
||||
"protocol.ts",
|
||||
"scriptInfo.ts",
|
||||
"scriptVersionCache.ts",
|
||||
"session.ts",
|
||||
"shared.ts",
|
||||
"types.ts",
|
||||
"typingsCache.ts",
|
||||
"utilities.ts",
|
||||
].map(function (f) {
|
||||
return path.join(serverDirectory, f);
|
||||
});
|
||||
|
||||
var serverCoreSources = [
|
||||
"server.ts"
|
||||
].map(function (f) {
|
||||
return path.join(serverDirectory, f);
|
||||
}).concat(baseServerCoreSources);
|
||||
|
||||
var cancellationTokenSources = [
|
||||
"cancellationToken.ts"
|
||||
].map(function (f) {
|
||||
return path.join(cancellationTokenDirectory, f);
|
||||
});
|
||||
|
||||
var typingsInstallerSources = [
|
||||
"../types.ts",
|
||||
"../shared.ts",
|
||||
"typingsInstaller.ts",
|
||||
"nodeTypingsInstaller.ts"
|
||||
].map(function (f) {
|
||||
return path.join(typingsInstallerDirectory, f);
|
||||
});
|
||||
|
||||
var serverSources = serverCoreSources.concat(servicesSources);
|
||||
var languageServiceLibrarySources = baseServerCoreSources.concat(servicesSources);
|
||||
var compilerSources = filesFromConfig("./src/compiler/tsconfig.json");
|
||||
var servicesSources = filesFromConfig("./src/services/tsconfig.json");
|
||||
var cancellationTokenSources = filesFromConfig(path.join(serverDirectory, "cancellationToken/tsconfig.json"));
|
||||
var typingsInstallerSources = filesFromConfig(path.join(serverDirectory, "typingsInstaller/tsconfig.json"));
|
||||
var watchGuardSources = filesFromConfig(path.join(serverDirectory, "watchGuard/tsconfig.json"));
|
||||
var serverSources = filesFromConfig(path.join(serverDirectory, "tsconfig.json"))
|
||||
var languageServiceLibrarySources = filesFromConfig(path.join(serverDirectory, "tsconfig.library.json"));
|
||||
|
||||
var harnessCoreSources = [
|
||||
"harness.ts",
|
||||
@@ -269,6 +127,10 @@ var harnessSources = harnessCoreSources.concat([
|
||||
"projectErrors.ts",
|
||||
"matchFiles.ts",
|
||||
"initializeTSConfig.ts",
|
||||
"printer.ts",
|
||||
"textChanges.ts",
|
||||
"transform.ts",
|
||||
"customTransforms.ts",
|
||||
].map(function (f) {
|
||||
return path.join(unittestsDirectory, f);
|
||||
})).concat([
|
||||
@@ -310,13 +172,21 @@ var es2016LibrarySourceMap = es2016LibrarySource.map(function (source) {
|
||||
var es2017LibrarySource = [
|
||||
"es2017.object.d.ts",
|
||||
"es2017.sharedmemory.d.ts",
|
||||
"es2017.string.d.ts",
|
||||
"es2017.string.d.ts"
|
||||
];
|
||||
|
||||
var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
var esnextLibrarySource = [
|
||||
"esnext.asynciterable.d.ts"
|
||||
];
|
||||
|
||||
var esnextLibrarySourceMap = esnextLibrarySource.map(function (source) {
|
||||
return { target: "lib." + source, sources: ["header.d.ts", source] };
|
||||
});
|
||||
|
||||
var hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];
|
||||
|
||||
var librarySourceMap = [
|
||||
@@ -331,11 +201,15 @@ var librarySourceMap = [
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
{ target: "lib.esnext.d.ts", sources: ["header.d.ts", "esnext.d.ts"] },
|
||||
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap);
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") },
|
||||
{ target: "lib.es2016.full.d.ts", sources: ["header.d.ts", "es2016.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") },
|
||||
{ target: "lib.es2017.full.d.ts", sources: ["header.d.ts", "es2017.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") },
|
||||
{ target: "lib.esnext.full.d.ts", sources: ["header.d.ts", "esnext.d.ts"].concat(hostsLibrarySources, "dom.iterable.d.ts") },
|
||||
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap, esnextLibrarySourceMap);
|
||||
|
||||
var libraryTargets = librarySourceMap.map(function (f) {
|
||||
return path.join(builtLocalDirectory, f.target);
|
||||
@@ -442,21 +316,29 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
if (useDebugMode) {
|
||||
if (opts.inlineSourceMap) {
|
||||
options += " --inlineSourceMap --inlineSources";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
options += " -sourcemap";
|
||||
if (!opts.noMapRoot) {
|
||||
options += " -mapRoot file:///" + path.resolve(path.dirname(outFile));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
options += " --newLine LF";
|
||||
}
|
||||
|
||||
if (opts.stripInternal) {
|
||||
options += " --stripInternal";
|
||||
}
|
||||
|
||||
options += " --target es5 --noUnusedLocals --noUnusedParameters";
|
||||
options += " --target es5";
|
||||
if (opts.lib) {
|
||||
options += " --lib " + opts.lib
|
||||
}
|
||||
else {
|
||||
options += " --lib es5"
|
||||
}
|
||||
options += " --noUnusedLocals --noUnusedParameters";
|
||||
|
||||
var cmd = host + " " + compilerPath + " " + options + " ";
|
||||
cmd = cmd + sources.join(" ");
|
||||
@@ -543,7 +425,7 @@ compileFile(buildProtocolJs,
|
||||
[buildProtocolTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false,
|
||||
{noOutFile: true});
|
||||
{ noOutFile: true, lib: "es6" });
|
||||
|
||||
file(buildProtocolDts, [buildProtocolTs, buildProtocolJs, typescriptServicesDts], function() {
|
||||
|
||||
@@ -705,13 +587,16 @@ compileFile(
|
||||
file(typescriptServicesDts, [servicesFile]);
|
||||
|
||||
var cancellationTokenFile = path.join(builtLocalDirectory, "cancellationToken.js");
|
||||
compileFile(cancellationTokenFile, cancellationTokenSources, [builtLocalDirectory].concat(cancellationTokenSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: true });
|
||||
compileFile(cancellationTokenFile, cancellationTokenSources, [builtLocalDirectory].concat(cancellationTokenSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: true, lib: "es6" });
|
||||
|
||||
var typingsInstallerFile = path.join(builtLocalDirectory, "typingsInstaller.js");
|
||||
compileFile(typingsInstallerFile, typingsInstallerSources, [builtLocalDirectory].concat(typingsInstallerSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: false });
|
||||
compileFile(typingsInstallerFile, typingsInstallerSources, [builtLocalDirectory].concat(typingsInstallerSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: false, lib: "es6" });
|
||||
|
||||
var watchGuardFile = path.join(builtLocalDirectory, "watchGuard.js");
|
||||
compileFile(watchGuardFile, watchGuardSources, [builtLocalDirectory].concat(watchGuardSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: false, lib: "es6" });
|
||||
|
||||
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"] });
|
||||
compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile, watchGuardFile].concat(serverSources).concat(servicesSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true, lib: "es6" });
|
||||
var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
|
||||
var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts");
|
||||
compileFile(
|
||||
@@ -720,13 +605,13 @@ compileFile(
|
||||
[builtLocalDirectory, copyright, builtLocalCompiler].concat(languageServiceLibrarySources).concat(libraryTargets),
|
||||
/*prefixes*/[copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
{ noOutFile: false, generateDeclarations: true, stripInternal: true },
|
||||
{ noOutFile: false, generateDeclarations: true, stripInternal: true, preserveConstEnums: true },
|
||||
/*callback*/ function () {
|
||||
prependFile(copyright, tsserverLibraryDefinitionFile);
|
||||
|
||||
// Appending exports at the end of the server library
|
||||
var tsserverLibraryDefinitionFileContents =
|
||||
fs.readFileSync(tsserverLibraryDefinitionFile).toString() +
|
||||
fs.readFileSync(tsserverLibraryDefinitionFile).toString() +
|
||||
"\r\nexport = ts;" +
|
||||
"\r\nexport as namespace ts;";
|
||||
|
||||
@@ -805,7 +690,7 @@ task("generate-spec", [specMd]);
|
||||
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
|
||||
desc("Makes a new LKG out of the built js files");
|
||||
task("LKG", ["clean", "release", "local"].concat(libraryTargets), function () {
|
||||
var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, cancellationTokenFile, typingsInstallerFile, buildProtocolDts].concat(libraryTargets);
|
||||
var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, cancellationTokenFile, typingsInstallerFile, buildProtocolDts, watchGuardFile].concat(libraryTargets);
|
||||
var missingFiles = expectedFiles.filter(function (f) {
|
||||
return !fs.existsSync(f);
|
||||
});
|
||||
@@ -835,7 +720,7 @@ compileFile(
|
||||
/*prereqs*/[builtLocalDirectory, tscFile].concat(libraryTargets).concat(servicesSources).concat(harnessSources),
|
||||
/*prefixes*/[],
|
||||
/*useBuiltCompiler:*/ true,
|
||||
/*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"] });
|
||||
/*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"], lib: "es6" });
|
||||
|
||||
var internalTests = "internal/";
|
||||
|
||||
@@ -869,7 +754,8 @@ function exec(cmd, completeHandler, errorHandler) {
|
||||
ex.addListener("error", function (e, status) {
|
||||
if (errorHandler) {
|
||||
errorHandler(e, status);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fail("Process exited with code " + status);
|
||||
}
|
||||
});
|
||||
@@ -918,6 +804,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
}
|
||||
|
||||
var debug = process.env.debug || process.env.d;
|
||||
var inspect = process.env.inspect;
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var light = process.env.light || false;
|
||||
var stackTraceLimit = process.env.stackTraceLimit;
|
||||
@@ -947,18 +834,39 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
testTimeout = 800000;
|
||||
}
|
||||
|
||||
colors = process.env.colors || process.env.color;
|
||||
colors = colors ? ' --no-colors ' : ' --colors ';
|
||||
reporter = process.env.reporter || process.env.r || defaultReporter;
|
||||
var bail = (process.env.bail || process.env.b) ? "--bail" : "";
|
||||
var colors = process.env.colors || process.env.color || true;
|
||||
var reporter = process.env.reporter || process.env.r || defaultReporter;
|
||||
var bail = process.env.bail || process.env.b;
|
||||
var lintFlag = process.env.lint !== 'false';
|
||||
|
||||
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
|
||||
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
|
||||
if (!runInParallel) {
|
||||
var startTime = mark();
|
||||
tests = tests ? ' -g "' + tests + '"' : '';
|
||||
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + bail + ' -t ' + testTimeout + ' ' + run;
|
||||
var args = [];
|
||||
if (inspect) {
|
||||
args.push("--inspect");
|
||||
}
|
||||
if (inspect || debug) {
|
||||
args.push("--debug-brk");
|
||||
}
|
||||
args.push("-R", reporter);
|
||||
if (tests) {
|
||||
args.push("-g", `"${tests}"`);
|
||||
}
|
||||
if (colors) {
|
||||
args.push("--colors");
|
||||
}
|
||||
else {
|
||||
args.push("--no-colors");
|
||||
}
|
||||
if (bail) {
|
||||
args.push("--bail");
|
||||
}
|
||||
args.push("-t", testTimeout);
|
||||
args.push(run);
|
||||
|
||||
var cmd = "mocha " + args.join(" ");
|
||||
console.log(cmd);
|
||||
|
||||
var savedNodeEnv = process.env.NODE_ENV;
|
||||
@@ -979,7 +887,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
var savedNodeEnv = process.env.NODE_ENV;
|
||||
process.env.NODE_ENV = "development";
|
||||
var startTime = mark();
|
||||
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
|
||||
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: !colors }, function (err) {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
measure(startTime);
|
||||
// last worker clean everything and runs linter in case if there were no errors
|
||||
@@ -1041,7 +949,7 @@ task("generate-code-coverage", ["tests", builtLocalDirectory], function () {
|
||||
// Browser tests
|
||||
var nodeServerOutFile = "tests/webTestServer.js";
|
||||
var nodeServerInFile = "tests/webTestServer.ts";
|
||||
compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, { noOutFile: true });
|
||||
compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, { noOutFile: true, lib: "es6" });
|
||||
|
||||
desc("Runs browserify on run.js to produce a file suitable for running tests in the browser");
|
||||
task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() {
|
||||
@@ -1105,21 +1013,32 @@ task("baseline-accept", function () {
|
||||
|
||||
function acceptBaseline(sourceFolder, targetFolder) {
|
||||
console.log('Accept baselines from ' + sourceFolder + ' to ' + targetFolder);
|
||||
var files = fs.readdirSync(sourceFolder);
|
||||
var deleteEnding = '.delete';
|
||||
for (var i in files) {
|
||||
var filename = files[i];
|
||||
var fullLocalPath = path.join(sourceFolder, filename);
|
||||
if (fs.statSync(fullLocalPath).isFile()) {
|
||||
if (filename.substr(filename.length - deleteEnding.length) === deleteEnding) {
|
||||
filename = filename.substr(0, filename.length - deleteEnding.length);
|
||||
fs.unlinkSync(path.join(targetFolder, filename));
|
||||
} else {
|
||||
var target = path.join(targetFolder, filename);
|
||||
if (fs.existsSync(target)) {
|
||||
fs.unlinkSync(target);
|
||||
|
||||
acceptBaselineFolder(sourceFolder, targetFolder);
|
||||
|
||||
function acceptBaselineFolder(sourceFolder, targetFolder) {
|
||||
var files = fs.readdirSync(sourceFolder);
|
||||
|
||||
for (var i in files) {
|
||||
var filename = files[i];
|
||||
var fullLocalPath = path.join(sourceFolder, filename);
|
||||
var stat = fs.statSync(fullLocalPath);
|
||||
if (stat.isFile()) {
|
||||
if (filename.substr(filename.length - deleteEnding.length) === deleteEnding) {
|
||||
filename = filename.substr(0, filename.length - deleteEnding.length);
|
||||
fs.unlinkSync(path.join(targetFolder, filename));
|
||||
}
|
||||
fs.renameSync(path.join(sourceFolder, filename), target);
|
||||
else {
|
||||
var target = path.join(targetFolder, filename);
|
||||
if (fs.existsSync(target)) {
|
||||
fs.unlinkSync(target);
|
||||
}
|
||||
fs.renameSync(path.join(sourceFolder, filename), target);
|
||||
}
|
||||
}
|
||||
else if (stat.isDirectory()) {
|
||||
acceptBaselineFolder(fullLocalPath, path.join(targetFolder, filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1200,7 +1119,8 @@ var tslintRules = [
|
||||
"noInOperatorRule",
|
||||
"noIncrementDecrementRule",
|
||||
"objectLiteralSurroundingSpaceRule",
|
||||
"noTypeAssertionWhitespaceRule"
|
||||
"noTypeAssertionWhitespaceRule",
|
||||
"noBomRule"
|
||||
];
|
||||
var tslintRulesFiles = tslintRules.map(function (p) {
|
||||
return path.join(tslintRuleDir, p + ".ts");
|
||||
@@ -1212,7 +1132,7 @@ desc("Compiles tslint rules to js");
|
||||
task("build-rules", ["build-rules-start"].concat(tslintRulesOutFiles).concat(["build-rules-end"]));
|
||||
tslintRulesFiles.forEach(function (ruleFile, i) {
|
||||
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false,
|
||||
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint") });
|
||||
{ noOutFile: true, generateDeclarations: false, outDir: path.join(builtLocalDirectory, "tslint"), lib: "es6" });
|
||||
});
|
||||
|
||||
desc("Emit the start of the build-rules fold");
|
||||
@@ -1229,13 +1149,16 @@ var lintTargets = compilerSources
|
||||
.concat(harnessSources)
|
||||
// Other harness sources
|
||||
.concat(["instrumenter.ts"].map(function (f) { return path.join(harnessDirectory, f) }))
|
||||
.concat(serverCoreSources)
|
||||
.concat(serverSources)
|
||||
.concat(tslintRulesFiles)
|
||||
.concat(servicesSources)
|
||||
.concat(typingsInstallerSources)
|
||||
.concat(cancellationTokenSources)
|
||||
.concat(["Gulpfile.ts"])
|
||||
.concat([nodeServerInFile, perftscPath, "tests/perfsys.ts", webhostPath]);
|
||||
.concat([nodeServerInFile, perftscPath, "tests/perfsys.ts", webhostPath])
|
||||
.map(function (p) { return path.resolve(p) });
|
||||
// keep only unique items
|
||||
lintTargets = Array.from(new Set(lintTargets));
|
||||
|
||||
function sendNextFile(files, child, callback, failures) {
|
||||
var file = files.pop();
|
||||
@@ -1272,43 +1195,16 @@ function spawnLintWorker(files, callback) {
|
||||
}
|
||||
|
||||
desc("Runs tslint on the compiler sources. Optional arguments are: f[iles]=regex");
|
||||
task("lint", ["build-rules"], function () {
|
||||
task("lint", ["build-rules"], () => {
|
||||
if (fold.isTravis()) console.log(fold.start("lint"));
|
||||
var startTime = mark();
|
||||
var failed = 0;
|
||||
var fileMatcher = RegExp(process.env.f || process.env.file || process.env.files || "");
|
||||
var done = {};
|
||||
for (var i in lintTargets) {
|
||||
var target = lintTargets[i];
|
||||
if (!done[target] && fileMatcher.test(target)) {
|
||||
done[target] = fs.statSync(target).size;
|
||||
}
|
||||
}
|
||||
|
||||
var workerCount = (process.env.workerCount && +process.env.workerCount) || os.cpus().length;
|
||||
|
||||
var names = Object.keys(done).sort(function (namea, nameb) {
|
||||
return done[namea] - done[nameb];
|
||||
const fileMatcher = process.env.f || process.env.file || process.env.files;
|
||||
const files = fileMatcher
|
||||
? `src/**/${fileMatcher}`
|
||||
: "Gulpfile.ts 'scripts/tslint/*.ts' 'src/**/*.ts' --exclude src/lib/es5.d.ts --exclude 'src/lib/*.generated.d.ts'";
|
||||
const cmd = `node node_modules/tslint/bin/tslint ${files} --format stylish`;
|
||||
console.log("Linting: " + cmd);
|
||||
jake.exec([cmd], { interactive: true }, () => {
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
complete();
|
||||
});
|
||||
|
||||
for (var i = 0; i < workerCount; i++) {
|
||||
spawnLintWorker(names, finished);
|
||||
}
|
||||
|
||||
var completed = 0;
|
||||
var failures = 0;
|
||||
function finished(fails) {
|
||||
completed++;
|
||||
failures += fails;
|
||||
if (completed === workerCount) {
|
||||
measure(startTime);
|
||||
if (fold.isTravis()) console.log(fold.end("lint"));
|
||||
if (failures > 0) {
|
||||
fail('Linter errors.', failed);
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, { async: true });
|
||||
});
|
||||
|
||||
@@ -39,8 +39,8 @@ with any additional questions or comments.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Quick tutorial](http://www.typescriptlang.org/Tutorial)
|
||||
* [Programming handbook](http://www.typescriptlang.org/Handbook)
|
||||
* [Quick tutorial](http://www.typescriptlang.org/docs/tutorial.html)
|
||||
* [Programming handbook](http://www.typescriptlang.org/docs/handbook/basic-types.html)
|
||||
* [Language specification](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md)
|
||||
* [Homepage](http://www.typescriptlang.org/)
|
||||
|
||||
@@ -95,4 +95,4 @@ node built/local/tsc.js hello.ts
|
||||
|
||||
## Roadmap
|
||||
|
||||
For details on our planned features and future direction please refer to our [roadmap](https://github.com/Microsoft/TypeScript/wiki/Roadmap).
|
||||
For details on our planned features and future direction please refer to our [roadmap](https://github.com/Microsoft/TypeScript/wiki/Roadmap).
|
||||
|
||||
+10
-15
@@ -1,15 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" id="logo-typescript" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.09 69.57">
|
||||
<g fill="#007ACC">
|
||||
<path d="M34.98 7.56H20.43v45.07h-5.91V7.56H0V2.21h34.98V7.56z"/>
|
||||
<path d="M57.94 16.63L41.38 58.39c-2.95 7.45-7.1 11.18-12.45 11.18 -1.5 0-2.75-0.15-3.76-0.46v-5.17c1.24 0.42 2.38 0.63 3.41 0.63 2.91 0 5.09-1.73 6.54-5.2l2.88-6.82L23.94 16.63h6.4l9.74 27.7c0.12 0.35 0.36 1.27 0.74 2.74h0.21c0.12-0.56 0.35-1.45 0.7-2.67l10.23-27.77H57.94z"/>
|
||||
<path d="M67.37 47.43h-0.14v21.76h-5.77V16.63h5.77v6.33h0.14c2.84-4.78 6.98-7.17 12.45-7.17 4.64 0 8.26 1.61 10.86 4.83 2.6 3.22 3.9 7.54 3.9 12.96 0 6.02-1.46 10.85-4.39 14.47 -2.93 3.62-6.94 5.43-12.02 5.43C73.5 53.47 69.9 51.46 67.37 47.43zM67.23 32.91v5.03c0 2.98 0.97 5.5 2.9 7.58s4.39 3.11 7.37 3.11c3.49 0 6.23-1.34 8.21-4.01 1.98-2.67 2.97-6.39 2.97-11.14 0-4.01-0.93-7.15-2.78-9.42 -1.85-2.27-4.36-3.41-7.52-3.41 -3.35 0-6.05 1.17-8.09 3.5C68.25 26.47 67.23 29.39 67.23 32.91z"/>
|
||||
<path d="M129.56 36.07h-25.42c0.09 4.01 1.17 7.1 3.23 9.28 2.06 2.18 4.9 3.27 8.51 3.27 4.05 0 7.78-1.34 11.18-4.01v5.41c-3.16 2.3-7.35 3.45-12.55 3.45 -5.09 0-9.08-1.63-11.99-4.9 -2.91-3.27-4.36-7.87-4.36-13.8 0-5.6 1.59-10.17 4.76-13.69 3.18-3.53 7.12-5.29 11.83-5.29s8.35 1.52 10.93 4.57c2.58 3.05 3.87 7.28 3.87 12.69V36.07zM123.65 31.18c-0.02-3.33-0.83-5.92-2.41-7.77 -1.58-1.85-3.78-2.78-6.59-2.78 -2.72 0-5.03 0.97-6.93 2.92 -1.9 1.95-3.07 4.49-3.52 7.63H123.65z"/>
|
||||
<path d="M134.6 50.59v-6.96c0.73 0.7 1.6 1.34 2.62 1.9 1.02 0.56 2.09 1.04 3.22 1.42s2.26 0.69 3.39 0.9c1.14 0.21 2.19 0.32 3.15 0.32 3.32 0 5.81-0.67 7.45-2.02 1.64-1.35 2.46-3.29 2.46-5.82 0-1.36-0.27-2.54-0.82-3.55 -0.55-1.01-1.3-1.93-2.27-2.76s-2.11-1.63-3.43-2.39c-1.32-0.76-2.74-1.56-4.26-2.41 -1.61-0.89-3.11-1.79-4.5-2.71 -1.39-0.91-2.61-1.92-3.63-3.02 -1.03-1.1-1.84-2.35-2.43-3.74 -0.59-1.39-0.88-3.03-0.88-4.9 0-2.3 0.46-4.29 1.38-5.99 0.92-1.7 2.13-3.1 3.64-4.2 1.5-1.1 3.21-1.92 5.13-2.46 1.92-0.54 3.88-0.81 5.87-0.81 4.55 0 7.86 0.6 9.94 1.79v6.64c-2.72-2.06-6.22-3.09-10.49-3.09 -1.18 0-2.36 0.14-3.54 0.4 -1.18 0.27-2.23 0.71-3.15 1.32 -0.92 0.61-1.67 1.39-2.25 2.36 -0.58 0.96-0.87 2.13-0.87 3.52 0 1.29 0.22 2.4 0.66 3.34 0.44 0.94 1.09 1.79 1.95 2.57 0.86 0.77 1.9 1.52 3.14 2.25 1.23 0.73 2.65 1.52 4.26 2.39 1.65 0.89 3.22 1.83 4.7 2.81s2.78 2.07 3.89 3.27c1.11 1.2 2 2.52 2.65 3.97 0.65 1.45 0.98 3.12 0.98 4.99 0 2.48-0.45 4.59-1.33 6.31 -0.89 1.72-2.09 3.12-3.6 4.2 -1.51 1.08-3.25 1.86-5.23 2.34 -1.97 0.48-4.05 0.72-6.24 0.72 -0.73 0-1.63-0.06-2.7-0.19s-2.17-0.32-3.28-0.56c-1.12-0.25-2.17-0.55-3.17-0.91C136 51.44 135.21 51.03 134.6 50.59z"/>
|
||||
<path d="M193.25 50.98c-2.77 1.66-6.05 2.5-9.84 2.5 -5.13 0-9.28-1.67-12.43-5.01s-4.73-7.67-4.73-12.99c0-5.93 1.7-10.69 5.1-14.29 3.4-3.6 7.93-5.4 13.61-5.4 3.16 0 5.95 0.59 8.37 1.76v5.91c-2.67-1.88-5.53-2.81-8.58-2.81 -3.68 0-6.7 1.32-9.05 3.96s-3.53 6.1-3.53 10.39c0 4.22 1.11 7.55 3.32 9.98s5.19 3.66 8.91 3.66c3.14 0 6.09-1.04 8.86-3.13V50.98z"/>
|
||||
<path d="M215.56 22.46c-1.01-0.77-2.46-1.16-4.36-1.16 -2.46 0-4.52 1.16-6.17 3.48s-2.48 5.48-2.48 9.49v18.35h-5.77v-36h5.77v7.42h0.14c0.82-2.53 2.07-4.51 3.76-5.92 1.69-1.42 3.57-2.13 5.66-2.13 1.5 0 2.65 0.16 3.45 0.49V22.46z"/>
|
||||
<path d="M222.18 7.49c-1.03 0-1.91-0.35-2.64-1.05s-1.09-1.59-1.09-2.67c0-1.08 0.36-1.97 1.09-2.69 0.73-0.71 1.61-1.07 2.64-1.07 1.05 0 1.95 0.36 2.69 1.07 0.74 0.72 1.11 1.61 1.11 2.69 0 1.03-0.37 1.91-1.11 2.64C224.13 7.12 223.23 7.49 222.18 7.49zM224.99 52.63h-5.77v-36h5.77V52.63z"/>
|
||||
<path d="M234.29 47.43h-0.14v21.76h-5.77V16.63h5.77v6.33h0.14c2.84-4.78 6.98-7.17 12.45-7.17 4.64 0 8.26 1.61 10.86 4.83 2.6 3.22 3.9 7.54 3.9 12.96 0 6.02-1.46 10.85-4.39 14.47s-6.94 5.43-12.02 5.43C240.42 53.47 236.82 51.46 234.29 47.43zM234.15 32.91v5.03c0 2.98 0.97 5.5 2.9 7.58s4.39 3.11 7.37 3.11c3.49 0 6.23-1.34 8.21-4.01s2.97-6.39 2.97-11.14c0-4.01-0.93-7.15-2.78-9.42 -1.85-2.27-4.36-3.41-7.52-3.41 -3.35 0-6.05 1.17-8.09 3.5C235.17 26.47 234.15 29.39 234.15 32.91z"/>
|
||||
<path d="M283.09 52.28c-1.36 0.75-3.15 1.12-5.38 1.12 -6.3 0-9.46-3.52-9.46-10.55v-21.3h-6.19v-4.92h6.19V7.84l5.77-1.86v10.65h9.07v4.92h-9.07v20.28c0 2.41 0.41 4.14 1.23 5.17s2.18 1.55 4.08 1.55c1.45 0 2.71-0.4 3.76-1.2V52.28z"/>
|
||||
</g>
|
||||
</svg>
|
||||
<svg id="logo-typescript" xmlns="http://www.w3.org/2000/svg" viewBox="-64.9 417 216.5 51.9">
|
||||
<style>
|
||||
.st0 {
|
||||
fill: #000
|
||||
}
|
||||
</style>
|
||||
<path class="st0" d="M-38.2 421.7h-11.1V456h-4.5v-34.3h-11.1v-4.1h26.6v4.1h.1z" />
|
||||
<path class="st0" d="M-16.9 428.6l-12.6 31.8c-2.3 5.7-5.4 8.5-9.5 8.5-1.1 0-2.1-.1-2.9-.3v-3.9c.9.3 1.8.5 2.6.5 2.2 0 3.9-1.3 5-4l2.2-5.2-10.7-27.4h4.9l7.4 21.1c.1.3.3 1 .6 2.1h.2c.1-.4.3-1.1.5-2l7.8-21.2h4.5zM-9.5 452.1h-.1v16.6H-14v-40h4.4v4.8h.1c2.2-3.6 5.3-5.5 9.5-5.5 3.5 0 6.3 1.2 8.3 3.7s3 5.7 3 9.9c0 4.6-1.1 8.3-3.3 11s-5.3 4.1-9.2 4.1c-3.6 0-6.3-1.5-8.3-4.6zm-.1-11.1v3.8c0 2.3.7 4.2 2.2 5.8s3.3 2.4 5.6 2.4c2.7 0 4.7-1 6.3-3.1 1.6-2.1 2.3-4.9 2.3-8.5 0-3.1-.7-5.4-2.1-7.2-1.4-1.7-3.3-2.6-5.7-2.6-2.6 0-4.6.9-6.2 2.7-1.6 1.8-2.4 4-2.4 6.7zM38.4 443.4H19c.1 3.1.9 5.4 2.5 7.1s3.7 2.5 6.5 2.5c3.1 0 5.9-1 8.5-3.1v4.1c-2.4 1.8-5.6 2.6-9.6 2.6-3.9 0-6.9-1.2-9.1-3.7-2.2-2.5-3.3-6-3.3-10.5 0-4.3 1.2-7.7 3.6-10.4 2.4-2.7 5.4-4 9-4s6.4 1.2 8.3 3.5c2 2.3 2.9 5.5 2.9 9.7v2.2h.1zm-4.5-3.7c0-2.5-.6-4.5-1.8-5.9-1.2-1.4-2.9-2.1-5-2.1s-3.8.7-5.3 2.2c-1.4 1.5-2.3 3.4-2.7 5.8h14.8zM40.8 454.7v-3c2.8 1.8 5.5 2.6 8.4 2.6 3 0 5.3-.6 6.8-1.9 1.6-1.2 2.3-3 2.3-5.2 0-2-.5-3.5-1.6-4.7-1-1.2-3.3-2.8-6.8-4.8-3.9-2.3-6.4-4.2-7.4-5.7s-1.6-3.3-1.6-5.3c0-2.7 1.1-5 3.2-6.9 2.1-1.9 4.9-2.8 8.4-2.8 2.3 0 4.6.4 6.9 1.2v2.8c-2.3-1-4.7-1.5-7.2-1.5-2.6 0-4.7.7-6.2 2s-2.3 3-2.3 5 .5 3.5 1.6 4.7c1 1.2 3.3 2.7 6.8 4.7 3.6 2 6 3.8 7.2 5.4 1.2 1.6 1.8 3.4 1.8 5.5 0 2.9-1 5.3-3.1 7.2-2 1.9-4.9 2.8-8.7 2.8-1.3 0-2.8-.2-4.6-.6-1.6-.5-2.9-1-3.9-1.5zM84.3 454.8c-2 1.2-4.5 1.9-7.3 1.9-3.7 0-6.7-1.3-9-3.8-2.3-2.6-3.4-5.9-3.4-10.1 0-4.4 1.3-7.9 3.9-10.7 2.6-2.8 5.9-4.2 9.9-4.2 2.1 0 4.1.4 6.1 1.3v2.8c-2-1.2-4.1-1.8-6.5-1.8-3.2 0-5.8 1.2-7.8 3.5s-3 5.3-3 9c0 3.6.9 6.4 2.7 8.6 1.8 2.2 4.2 3.2 7.2 3.2 2.7 0 5.1-.7 7.2-2.2v2.5zM100.9 431.2c-.8-.6-1.8-.9-2.9-.9-2.2 0-4 1.1-5.4 3.3-1.5 2.2-2.2 5.4-2.2 9.5V456H88v-27.4h2.4v6.1h.1c.6-2.1 1.6-3.7 3-4.9 1.4-1.2 2.9-1.7 4.7-1.7 1 0 1.9.2 2.7.5v2.6zM105.1 421.7c-.5 0-1-.2-1.4-.6s-.6-.9-.6-1.5.2-1.1.6-1.4c.4-.4.9-.5 1.4-.5.6 0 1 .2 1.5.5.4.4.6.8.6 1.4s-.2 1.1-.6 1.5c-.5.4-.9.6-1.5.6zm-1.2 34.4v-27.4h2.5v27.4h-2.5zM115 451.2h-.1v17.5h-2.5v-40h2.5v5.7h.1c1-2 2.4-3.6 4.2-4.7 1.8-1.1 3.8-1.6 6-1.6 3.5 0 6.2 1.2 8.2 3.6 2 2.4 2.9 5.7 2.9 9.8 0 4.6-1.1 8.3-3.4 11.1-2.2 2.8-5.2 4.2-8.9 4.2-4-.1-7-1.9-9-5.6zm-.1-10.2v3.5c0 2.8.9 5.1 2.6 7.1s4 3 6.8 3 5.1-1.2 6.8-3.6c1.7-2.4 2.6-5.6 2.6-9.5 0-3.4-.8-6.2-2.4-8.2s-3.8-3-6.4-3c-3.2 0-5.7 1.1-7.4 3.2-1.7 2.1-2.6 4.6-2.6 7.5zM151.6 455.7c-1.3.6-2.5.9-3.6.9-4.1 0-6.1-2.4-6.1-7.3v-18.4H137v-2.3h4.9v-7.1c.4-.1.8-.3 1.2-.4.4-.1.8-.3 1.2-.4v8h7.2v2.3h-7.2v18.1c0 1.9.3 3.3.9 4.1.6.8 1.6 1.3 3 1.3 1 0 2.1-.3 3.3-1v2.2h.1z"
|
||||
/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.7 KiB |
+1
-1
@@ -2,7 +2,7 @@
|
||||
<!-- QUESTIONS: This is not a general support forum! Ask Qs at http://stackoverflow.com/questions/tagged/typescript -->
|
||||
<!-- SUGGESTIONS: See https://github.com/Microsoft/TypeScript-wiki/blob/master/Writing-Good-Design-Proposals.md -->
|
||||
|
||||
**TypeScript Version:** 2.1.1 / nightly (2.2.0-dev.201xxxxx)
|
||||
**TypeScript Version:** 2.2.1 / nightly (2.2.0-dev.201xxxxx)
|
||||
|
||||
**Code**
|
||||
|
||||
|
||||
+41
-11
@@ -15,6 +15,15 @@ and limitations under the License.
|
||||
|
||||
"use strict";
|
||||
var fs = require("fs");
|
||||
function pipeExists(name) {
|
||||
try {
|
||||
fs.statSync(name);
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function createCancellationToken(args) {
|
||||
var cancellationPipeName;
|
||||
for (var i = 0; i < args.length - 1; i++) {
|
||||
@@ -24,18 +33,39 @@ function createCancellationToken(args) {
|
||||
}
|
||||
}
|
||||
if (!cancellationPipeName) {
|
||||
return { isCancellationRequested: function () { return false; } };
|
||||
return {
|
||||
isCancellationRequested: function () { return false; },
|
||||
setRequest: function (_requestId) { return void 0; },
|
||||
resetRequest: function (_requestId) { return void 0; }
|
||||
};
|
||||
}
|
||||
return {
|
||||
isCancellationRequested: function () {
|
||||
try {
|
||||
fs.statSync(cancellationPipeName);
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
if (cancellationPipeName.charAt(cancellationPipeName.length - 1) === "*") {
|
||||
var namePrefix_1 = cancellationPipeName.slice(0, -1);
|
||||
if (namePrefix_1.length === 0 || namePrefix_1.indexOf("*") >= 0) {
|
||||
throw new Error("Invalid name for template cancellation pipe: it should have length greater than 2 characters and contain only one '*'.");
|
||||
}
|
||||
};
|
||||
var perRequestPipeName_1;
|
||||
var currentRequestId_1;
|
||||
return {
|
||||
isCancellationRequested: function () { return perRequestPipeName_1 !== undefined && pipeExists(perRequestPipeName_1); },
|
||||
setRequest: function (requestId) {
|
||||
currentRequestId_1 = currentRequestId_1;
|
||||
perRequestPipeName_1 = namePrefix_1 + requestId;
|
||||
},
|
||||
resetRequest: function (requestId) {
|
||||
if (currentRequestId_1 !== requestId) {
|
||||
throw new Error("Mismatched request id, expected " + currentRequestId_1 + ", actual " + requestId);
|
||||
}
|
||||
perRequestPipeName_1 = undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
return {
|
||||
isCancellationRequested: function () { return pipeExists(cancellationPipeName); },
|
||||
setRequest: function (_requestId) { return void 0; },
|
||||
resetRequest: function (_requestId) { return void 0; }
|
||||
};
|
||||
}
|
||||
}
|
||||
module.exports = createCancellationToken;
|
||||
|
||||
Vendored
+1599
-418
File diff suppressed because it is too large
Load Diff
Vendored
+1583
-384
File diff suppressed because it is too large
Load Diff
Vendored
+4
-4
@@ -24,7 +24,7 @@ interface Map<K, V> {
|
||||
forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
|
||||
get(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): this;
|
||||
set(key: K, value: V): this;
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
@@ -42,16 +42,16 @@ interface ReadonlyMap<K, V> {
|
||||
readonly size: number;
|
||||
}
|
||||
|
||||
interface WeakMap<K, V> {
|
||||
interface WeakMap<K extends object, V> {
|
||||
delete(key: K): boolean;
|
||||
get(key: K): V | undefined;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): this;
|
||||
set(key: K, value: V): this;
|
||||
}
|
||||
|
||||
interface WeakMapConstructor {
|
||||
new (): WeakMap<any, any>;
|
||||
new <K, V>(entries?: [K, V][]): WeakMap<K, V>;
|
||||
new <K extends object, V>(entries?: [K, V][]): WeakMap<K, V>;
|
||||
readonly prototype: WeakMap<any, any>;
|
||||
}
|
||||
declare var WeakMap: WeakMapConstructor;
|
||||
|
||||
Vendored
+1
-1
@@ -345,7 +345,7 @@ interface ObjectConstructor {
|
||||
* @param o The object to change its prototype.
|
||||
* @param proto The value of the new prototype or null.
|
||||
*/
|
||||
setPrototypeOf(o: any, proto: any): any;
|
||||
setPrototypeOf(o: any, proto: object | null): any;
|
||||
|
||||
/**
|
||||
* Gets the own property descriptor of the specified object.
|
||||
|
||||
Vendored
+3
-3
@@ -119,10 +119,10 @@ interface MapConstructor {
|
||||
new <K, V>(iterable: Iterable<[K, V]>): Map<K, V>;
|
||||
}
|
||||
|
||||
interface WeakMap<K, V> { }
|
||||
interface WeakMap<K extends object, V> { }
|
||||
|
||||
interface WeakMapConstructor {
|
||||
new <K, V>(iterable: Iterable<[K, V]>): WeakMap<K, V>;
|
||||
new <K extends object, V>(iterable: Iterable<[K, V]>): WeakMap<K, V>;
|
||||
}
|
||||
|
||||
interface Set<T> {
|
||||
@@ -462,4 +462,4 @@ interface Float64ArrayConstructor {
|
||||
* @param thisArg Value of 'this' used to invoke the mapfn.
|
||||
*/
|
||||
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
-51
@@ -18,57 +18,6 @@ and limitations under the License.
|
||||
/// <reference no-default-lib="true"/>
|
||||
|
||||
|
||||
/**
|
||||
* Represents the completion of an asynchronous operation
|
||||
*/
|
||||
interface Promise<T> {
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then(onfulfilled?: ((value: T) => T | PromiseLike<T>) | undefined | null, onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): Promise<T>;
|
||||
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult>(onfulfilled: ((value: T) => T | PromiseLike<T>) | undefined | null, onrejected: (reason: any) => TResult | PromiseLike<TResult>): Promise<T | TResult>;
|
||||
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult>(onfulfilled: (value: T) => TResult | PromiseLike<TResult>, onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<TResult>;
|
||||
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult1, TResult2>(onfulfilled: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): Promise<TResult1 | TResult2>;
|
||||
|
||||
/**
|
||||
* Attaches a callback for only the rejection of the Promise.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of the callback.
|
||||
*/
|
||||
catch(onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): Promise<T>;
|
||||
|
||||
/**
|
||||
* Attaches a callback for only the rejection of the Promise.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of the callback.
|
||||
*/
|
||||
catch<TResult>(onrejected: (reason: any) => TResult | PromiseLike<TResult>): Promise<T | TResult>;
|
||||
}
|
||||
|
||||
interface PromiseConstructor {
|
||||
/**
|
||||
* A reference to the prototype.
|
||||
|
||||
Vendored
+2
-2
@@ -19,7 +19,7 @@ and limitations under the License.
|
||||
|
||||
|
||||
interface ProxyHandler<T> {
|
||||
getPrototypeOf? (target: T): {} | null;
|
||||
getPrototypeOf? (target: T): object | null;
|
||||
setPrototypeOf? (target: T, v: any): boolean;
|
||||
isExtensible? (target: T): boolean;
|
||||
preventExtensions? (target: T): boolean;
|
||||
@@ -32,7 +32,7 @@ interface ProxyHandler<T> {
|
||||
enumerate? (target: T): PropertyKey[];
|
||||
ownKeys? (target: T): PropertyKey[];
|
||||
apply? (target: T, thisArg: any, argArray?: any): any;
|
||||
construct? (target: T, argArray: any, newTarget?: any): {};
|
||||
construct? (target: T, argArray: any, newTarget?: any): object
|
||||
}
|
||||
|
||||
interface ProxyConstructor {
|
||||
|
||||
Vendored
+1
-1
@@ -23,7 +23,7 @@ interface Symbol {
|
||||
toString(): string;
|
||||
|
||||
/** Returns the primitive value of the specified object. */
|
||||
valueOf(): Object;
|
||||
valueOf(): symbol;
|
||||
}
|
||||
|
||||
interface SymbolConstructor {
|
||||
|
||||
Vendored
+2
-2
@@ -130,7 +130,7 @@ interface Map<K, V> {
|
||||
readonly [Symbol.toStringTag]: "Map";
|
||||
}
|
||||
|
||||
interface WeakMap<K, V>{
|
||||
interface WeakMap<K extends object, V>{
|
||||
readonly [Symbol.toStringTag]: "WeakMap";
|
||||
}
|
||||
|
||||
@@ -344,4 +344,4 @@ interface Float32Array {
|
||||
*/
|
||||
interface Float64Array {
|
||||
readonly [Symbol.toStringTag]: "Float64Array";
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+16
-34
@@ -157,23 +157,17 @@ interface ObjectConstructor {
|
||||
getOwnPropertyNames(o: any): string[];
|
||||
|
||||
/**
|
||||
* Creates an object that has null prototype.
|
||||
* @param o Object to use as a prototype. May be null
|
||||
* Creates an object that has the specified prototype or that has null prototype.
|
||||
* @param o Object to use as a prototype. May be null.
|
||||
*/
|
||||
create(o: null): any;
|
||||
|
||||
/**
|
||||
* Creates an object that has the specified prototype, and that optionally contains specified properties.
|
||||
* @param o Object to use as a prototype. May be null
|
||||
*/
|
||||
create<T>(o: T): T;
|
||||
create<T extends object>(o: T | null): T | object;
|
||||
|
||||
/**
|
||||
* Creates an object that has the specified prototype, and that optionally contains specified properties.
|
||||
* @param o Object to use as a prototype. May be null
|
||||
* @param properties JavaScript object that contains one or more property descriptors.
|
||||
*/
|
||||
create(o: any, properties: PropertyDescriptorMap): any;
|
||||
create(o: object | null, properties: PropertyDescriptorMap): any;
|
||||
|
||||
/**
|
||||
* Adds a property to an object, or modifies attributes of an existing property.
|
||||
@@ -361,14 +355,14 @@ interface String {
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using a regular expression or search string.
|
||||
* @param searchValue A string that represents the regular expression.
|
||||
* @param searchValue A string to search for.
|
||||
* @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
|
||||
*/
|
||||
replace(searchValue: string, replaceValue: string): string;
|
||||
|
||||
/**
|
||||
* Replaces text in a string, using a regular expression or search string.
|
||||
* @param searchValue A string that represents the regular expression.
|
||||
* @param searchValue A string to search for.
|
||||
* @param replacer A function that returns the replacement text.
|
||||
*/
|
||||
replace(searchValue: string, replacer: (substring: string, ...args: any[]) => string): string;
|
||||
@@ -1336,39 +1330,27 @@ interface PromiseLike<T> {
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then(
|
||||
onfulfilled?: ((value: T) => T | PromiseLike<T>) | undefined | null,
|
||||
onrejected?: ((reason: any) => T | PromiseLike<T>) | undefined | null): PromiseLike<T>;
|
||||
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the completion of an asynchronous operation
|
||||
*/
|
||||
interface Promise<T> {
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult>(
|
||||
onfulfilled: ((value: T) => T | PromiseLike<T>) | undefined | null,
|
||||
onrejected: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<T | TResult>;
|
||||
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
|
||||
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* Attaches a callback for only the rejection of the Promise.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
* @returns A Promise for the completion of the callback.
|
||||
*/
|
||||
then<TResult>(
|
||||
onfulfilled: (value: T) => TResult | PromiseLike<TResult>,
|
||||
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): PromiseLike<TResult>;
|
||||
|
||||
/**
|
||||
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
||||
* @param onfulfilled The callback to execute when the Promise is resolved.
|
||||
* @param onrejected The callback to execute when the Promise is rejected.
|
||||
* @returns A Promise for the completion of which ever callback is executed.
|
||||
*/
|
||||
then<TResult1, TResult2>(
|
||||
onfulfilled: (value: T) => TResult1 | PromiseLike<TResult1>,
|
||||
onrejected: (reason: any) => TResult2 | PromiseLike<TResult2>): PromiseLike<TResult1 | TResult2>;
|
||||
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
|
||||
}
|
||||
|
||||
interface ArrayLike<T> {
|
||||
|
||||
Vendored
+1611
-479
File diff suppressed because it is too large
Load Diff
Vendored
+636
-161
File diff suppressed because it is too large
Load Diff
Vendored
+32
-6
@@ -734,9 +734,9 @@ declare namespace ts.server.protocol {
|
||||
*/
|
||||
formatOptions?: FormatCodeSettings;
|
||||
/**
|
||||
* The host's additional supported file extensions
|
||||
* The host's additional supported .js file extensions
|
||||
*/
|
||||
extraFileExtensions?: FileExtensionInfo[];
|
||||
extraFileExtensions?: JsFileExtensionInfo[];
|
||||
}
|
||||
/**
|
||||
* Configure request; value of command field is "configure". Specifies
|
||||
@@ -905,6 +905,10 @@ declare namespace ts.server.protocol {
|
||||
* List of files names that should be recompiled
|
||||
*/
|
||||
fileNames: string[];
|
||||
/**
|
||||
* true if project uses outFile or out compiler option
|
||||
*/
|
||||
projectUsesOutFile: boolean;
|
||||
}
|
||||
/**
|
||||
* Response for CompileOnSaveAffectedFileListRequest request;
|
||||
@@ -1352,6 +1356,17 @@ declare namespace ts.server.protocol {
|
||||
command: CommandTypes.Geterr;
|
||||
arguments: GeterrRequestArgs;
|
||||
}
|
||||
type RequestCompletedEventName = "requestCompleted";
|
||||
/**
|
||||
* Event that is sent when server have finished processing request with specified id.
|
||||
*/
|
||||
interface RequestCompletedEvent extends Event {
|
||||
event: RequestCompletedEventName;
|
||||
body: RequestCompletedEventBody;
|
||||
}
|
||||
interface RequestCompletedEventBody {
|
||||
request_seq: number;
|
||||
}
|
||||
/**
|
||||
* Item of diagnostic information found in a DiagnosticEvent message.
|
||||
*/
|
||||
@@ -1727,6 +1742,7 @@ declare namespace ts.server.protocol {
|
||||
insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean;
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean;
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean;
|
||||
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces?: boolean;
|
||||
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean;
|
||||
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
|
||||
insertSpaceBeforeFunctionParenthesis?: boolean;
|
||||
@@ -1775,6 +1791,7 @@ declare namespace ts.server.protocol {
|
||||
outDir?: string;
|
||||
outFile?: string;
|
||||
paths?: MapLike<string[]>;
|
||||
plugins?: PluginImport[];
|
||||
preserveConstEnums?: boolean;
|
||||
project?: string;
|
||||
reactNamespace?: string;
|
||||
@@ -1798,9 +1815,10 @@ declare namespace ts.server.protocol {
|
||||
namespace JsxEmit {
|
||||
type None = "None";
|
||||
type Preserve = "Preserve";
|
||||
type ReactNative = "ReactNative";
|
||||
type React = "React";
|
||||
}
|
||||
type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React;
|
||||
type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React | JsxEmit.ReactNative;
|
||||
namespace ModuleKind {
|
||||
type None = "None";
|
||||
type CommonJS = "CommonJS";
|
||||
@@ -1856,17 +1874,25 @@ declare namespace ts.server.protocol {
|
||||
[option: string]: string[] | boolean | undefined;
|
||||
}
|
||||
|
||||
interface FileExtensionInfo {
|
||||
interface JsFileExtensionInfo {
|
||||
extension: string;
|
||||
scriptKind: ScriptKind;
|
||||
isMixedContent: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of objects whose values are all of the same type.
|
||||
* The `in` and `for-in` operators can *not* be safely used,
|
||||
* since `Object.prototype` may be modified by outside code.
|
||||
*/
|
||||
interface MapLike<T> {
|
||||
[index: string]: T;
|
||||
}
|
||||
|
||||
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]>;
|
||||
interface PluginImport {
|
||||
name: string;
|
||||
}
|
||||
|
||||
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[];
|
||||
}
|
||||
declare namespace ts {
|
||||
// these types are empty stubs for types from services and should not be used directly
|
||||
|
||||
+8913
-7677
File diff suppressed because it is too large
Load Diff
+22809
-19692
File diff suppressed because it is too large
Load Diff
Vendored
+975
-546
File diff suppressed because it is too large
Load Diff
+14880
-11770
File diff suppressed because it is too large
Load Diff
Vendored
+750
-210
File diff suppressed because it is too large
Load Diff
+13683
-12035
File diff suppressed because it is too large
Load Diff
Vendored
+750
-210
File diff suppressed because it is too large
Load Diff
+13683
-12035
File diff suppressed because it is too large
Load Diff
+472
-348
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -2,7 +2,7 @@
|
||||
"name": "typescript",
|
||||
"author": "Microsoft Corp.",
|
||||
"homepage": "http://typescriptlang.org/",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"license": "Apache-2.0",
|
||||
"description": "TypeScript is a language for application scale JavaScript development",
|
||||
"keywords": [
|
||||
@@ -60,7 +60,7 @@
|
||||
"gulp-insert": "latest",
|
||||
"gulp-newer": "latest",
|
||||
"gulp-sourcemaps": "latest",
|
||||
"gulp-typescript": "3.1.3",
|
||||
"gulp-typescript": "3.1.5",
|
||||
"into-stream": "latest",
|
||||
"istanbul": "latest",
|
||||
"jake": "latest",
|
||||
|
||||
@@ -167,7 +167,7 @@ function generateProtocolFile(protocolTs: string, typeScriptServicesDts: string)
|
||||
const sanityCheckProgram = getProgramWithProtocolText(protocolDts, /*includeTypeScriptServices*/ false);
|
||||
const diagnostics = [...sanityCheckProgram.getSyntacticDiagnostics(), ...sanityCheckProgram.getSemanticDiagnostics(), ...sanityCheckProgram.getGlobalDiagnostics()];
|
||||
if (diagnostics.length) {
|
||||
const flattenedDiagnostics = diagnostics.map(d => ts.flattenDiagnosticMessageText(d.messageText, "\n")).join("\n");
|
||||
const flattenedDiagnostics = diagnostics.map(d => `${ts.flattenDiagnosticMessageText(d.messageText, "\n")} at ${d.file.fileName} line ${d.start}`).join("\n");
|
||||
throw new Error(`Unexpected errors during sanity check: ${flattenedDiagnostics}`);
|
||||
}
|
||||
return protocolDts;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var tslint = require("tslint");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
function getLinterOptions() {
|
||||
return {
|
||||
@@ -9,7 +10,7 @@ function getLinterOptions() {
|
||||
};
|
||||
}
|
||||
function getLinterConfiguration() {
|
||||
return require("../tslint.json");
|
||||
return tslint.Configuration.loadConfigurationFromPath(path.join(__dirname, "../tslint.json"));
|
||||
}
|
||||
|
||||
function lintFileContents(options, configuration, path, contents) {
|
||||
|
||||
@@ -2,52 +2,94 @@ import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`;
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
const program = ts.createProgram([sourceFile.fileName], Lint.createCompilerOptions());
|
||||
const checker = program.getTypeChecker();
|
||||
return this.applyWithWalker(new BooleanTriviaWalker(checker, program.getSourceFile(sourceFile.fileName), this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, ctx => walk(ctx));
|
||||
}
|
||||
}
|
||||
|
||||
class BooleanTriviaWalker extends Lint.RuleWalker {
|
||||
constructor(private checker: ts.TypeChecker, file: ts.SourceFile, opts: Lint.IOptions) {
|
||||
super(file, opts);
|
||||
}
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
const { sourceFile } = ctx;
|
||||
ts.forEachChild(sourceFile, function recur(node: ts.Node): void {
|
||||
if (node.kind === ts.SyntaxKind.CallExpression) {
|
||||
checkCall(node as ts.CallExpression);
|
||||
}
|
||||
ts.forEachChild(node, recur);
|
||||
});
|
||||
|
||||
visitCallExpression(node: ts.CallExpression) {
|
||||
super.visitCallExpression(node);
|
||||
if (node.arguments && node.arguments.some(arg => arg.kind === ts.SyntaxKind.TrueKeyword || arg.kind === ts.SyntaxKind.FalseKeyword)) {
|
||||
const targetCallSignature = this.checker.getResolvedSignature(node);
|
||||
if (!!targetCallSignature) {
|
||||
const targetParameters = targetCallSignature.getParameters();
|
||||
const source = this.getSourceFile();
|
||||
for (let index = 0; index < targetParameters.length; index++) {
|
||||
const param = targetParameters[index];
|
||||
const arg = node.arguments[index];
|
||||
if (!(arg && param)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const argType = this.checker.getContextualType(arg);
|
||||
if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) {
|
||||
if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) {
|
||||
continue;
|
||||
}
|
||||
let triviaContent: string;
|
||||
const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0);
|
||||
if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) {
|
||||
triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); // +/-2 to remove /**/
|
||||
}
|
||||
|
||||
const paramName = param.getName();
|
||||
if (triviaContent !== paramName && triviaContent !== paramName + ":") {
|
||||
this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent)));
|
||||
}
|
||||
}
|
||||
}
|
||||
function checkCall(node: ts.CallExpression): void {
|
||||
if (!shouldIgnoreCalledExpression(node.expression)) {
|
||||
for (const arg of node.arguments) {
|
||||
checkArg(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Skip certain function/method names whose parameter names are not informative. */
|
||||
function shouldIgnoreCalledExpression(expression: ts.Expression): boolean {
|
||||
if (expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
|
||||
const methodName = (expression as ts.PropertyAccessExpression).name.text;
|
||||
if (methodName.indexOf("set") === 0) {
|
||||
return true;
|
||||
}
|
||||
switch (methodName) {
|
||||
case "apply":
|
||||
case "assert":
|
||||
case "call":
|
||||
case "equal":
|
||||
case "fail":
|
||||
case "isTrue":
|
||||
case "output":
|
||||
case "stringify":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (expression.kind === ts.SyntaxKind.Identifier) {
|
||||
const functionName = (expression as ts.Identifier).text;
|
||||
if (functionName.indexOf("set") === 0) {
|
||||
return true;
|
||||
}
|
||||
switch (functionName) {
|
||||
case "assert":
|
||||
case "contains":
|
||||
case "createAnonymousType":
|
||||
case "createImportSpecifier":
|
||||
case "createProperty":
|
||||
case "createSignature":
|
||||
case "resolveName":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkArg(arg: ts.Expression): void {
|
||||
if (!isTrivia(arg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ranges = ts.getTrailingCommentRanges(sourceFile.text, arg.pos) || ts.getLeadingCommentRanges(sourceFile.text, arg.pos);
|
||||
if (ranges === undefined || ranges.length !== 1 || ranges[0].kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
||||
ctx.addFailureAtNode(arg, "Tag boolean argument with parameter name");
|
||||
return;
|
||||
}
|
||||
|
||||
const range = ranges[0];
|
||||
const argStart = arg.getStart(sourceFile);
|
||||
if (range.end + 1 !== argStart && sourceFile.text.slice(range.end, argStart).indexOf("\n") === -1) {
|
||||
ctx.addFailureAtNode(arg, "There should be 1 space between an argument and its comment.");
|
||||
}
|
||||
}
|
||||
|
||||
function isTrivia(arg: ts.Expression): boolean {
|
||||
switch (arg.kind) {
|
||||
case ts.SyntaxKind.TrueKeyword:
|
||||
case ts.SyntaxKind.FalseKeyword:
|
||||
case ts.SyntaxKind.NullKeyword:
|
||||
return true;
|
||||
case ts.SyntaxKind.Identifier:
|
||||
return (arg as ts.Identifier).originalKeywordKind === ts.SyntaxKind.UndefinedKeyword;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,50 +9,56 @@ export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static ELSE_FAILURE_STRING = "'else' should not be on the same line as the preceeding block's curly brace";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new NextLineWalker(sourceFile, this.getOptions()));
|
||||
const options = this.getOptions().ruleArguments;
|
||||
const checkCatch = options.indexOf(OPTION_CATCH) !== -1;
|
||||
const checkElse = options.indexOf(OPTION_ELSE) !== -1;
|
||||
return this.applyWithFunction(sourceFile, ctx => walk(ctx, checkCatch, checkElse));
|
||||
}
|
||||
}
|
||||
|
||||
class NextLineWalker extends Lint.RuleWalker {
|
||||
public visitIfStatement(node: ts.IfStatement) {
|
||||
const sourceFile = node.getSourceFile();
|
||||
const thenStatement = node.thenStatement;
|
||||
|
||||
const elseStatement = node.elseStatement;
|
||||
if (!!elseStatement) {
|
||||
// find the else keyword
|
||||
const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword);
|
||||
if (this.hasOption(OPTION_ELSE) && !!elseKeyword) {
|
||||
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
|
||||
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
|
||||
if (thenStatementEndLoc.line === elseKeywordLoc.line) {
|
||||
const failure = this.createFailure(elseKeyword.getStart(sourceFile), elseKeyword.getWidth(sourceFile), Rule.ELSE_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boolean): void {
|
||||
const { sourceFile } = ctx;
|
||||
function recur(node: ts.Node): void {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.IfStatement:
|
||||
checkIf(node as ts.IfStatement);
|
||||
break;
|
||||
case ts.SyntaxKind.TryStatement:
|
||||
checkTry(node as ts.TryStatement);
|
||||
break;
|
||||
}
|
||||
|
||||
super.visitIfStatement(node);
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
|
||||
public visitTryStatement(node: ts.TryStatement) {
|
||||
const sourceFile = node.getSourceFile();
|
||||
const catchClause = node.catchClause;
|
||||
function checkIf(node: ts.IfStatement): void {
|
||||
const { thenStatement, elseStatement } = node;
|
||||
if (!elseStatement) {
|
||||
return;
|
||||
}
|
||||
|
||||
// "visit" try block
|
||||
const tryBlock = node.tryBlock;
|
||||
|
||||
if (this.hasOption(OPTION_CATCH) && !!catchClause) {
|
||||
const tryClosingBrace = tryBlock.getLastToken(sourceFile);
|
||||
const catchKeyword = catchClause.getFirstToken(sourceFile);
|
||||
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
|
||||
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
|
||||
if (tryClosingBraceLoc.line === catchKeywordLoc.line) {
|
||||
const failure = this.createFailure(catchKeyword.getStart(sourceFile), catchKeyword.getWidth(sourceFile), Rule.CATCH_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
// find the else keyword
|
||||
const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword);
|
||||
if (checkElse && !!elseKeyword) {
|
||||
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
|
||||
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
|
||||
if (thenStatementEndLoc.line === elseKeywordLoc.line) {
|
||||
ctx.addFailureAtNode(elseKeyword, Rule.ELSE_FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
super.visitTryStatement(node);
|
||||
}
|
||||
|
||||
function checkTry({ tryBlock, catchClause }: ts.TryStatement): void {
|
||||
if (!checkCatch || !catchClause) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tryClosingBrace = tryBlock.getLastToken(sourceFile);
|
||||
const catchKeyword = catchClause.getFirstToken(sourceFile);
|
||||
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
|
||||
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
|
||||
if (tryClosingBraceLoc.line === catchKeywordLoc.line) {
|
||||
ctx.addFailureAtNode(catchKeyword, Rule.CATCH_FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "This file has a BOM.";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
if (ctx.sourceFile.text[0] === "\ufeff") {
|
||||
ctx.addFailure(0, 1, Rule.FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,19 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "Don't use the 'in' keyword - use 'hasProperty' to check for key presence instead";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new InWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class InWalker extends Lint.RuleWalker {
|
||||
visitNode(node: ts.Node) {
|
||||
super.visitNode(node);
|
||||
if (node.kind === ts.SyntaxKind.InKeyword && node.parent && node.parent.kind === ts.SyntaxKind.BinaryExpression) {
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
ts.forEachChild(ctx.sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
if (node.kind === ts.SyntaxKind.InKeyword && node.parent.kind === ts.SyntaxKind.BinaryExpression) {
|
||||
ctx.addFailureAtNode(node, Rule.FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,55 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static POSTFIX_FAILURE_STRING = "Don't use '++' or '--' postfix operators outside statements or for loops.";
|
||||
public static PREFIX_FAILURE_STRING = "Don't use '++' or '--' prefix operators.";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new IncrementDecrementWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class IncrementDecrementWalker extends Lint.RuleWalker {
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
ts.forEachChild(ctx.sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.PrefixUnaryExpression:
|
||||
const { operator } = node as ts.PrefixUnaryExpression;
|
||||
if (operator === ts.SyntaxKind.PlusPlusToken || operator === ts.SyntaxKind.MinusMinusToken) {
|
||||
check(node as ts.PrefixUnaryExpression);
|
||||
}
|
||||
break;
|
||||
|
||||
visitPostfixUnaryExpression(node: ts.PostfixUnaryExpression) {
|
||||
super.visitPostfixUnaryExpression(node);
|
||||
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
|
||||
this.visitIncrementDecrement(node);
|
||||
case ts.SyntaxKind.PostfixUnaryExpression:
|
||||
check(node as ts.PostfixUnaryExpression);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
visitPrefixUnaryExpression(node: ts.PrefixUnaryExpression) {
|
||||
super.visitPrefixUnaryExpression(node);
|
||||
if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator == ts.SyntaxKind.MinusMinusToken) {
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.PREFIX_FAILURE_STRING));
|
||||
function check(node: ts.UnaryExpression): void {
|
||||
if (!isAllowedLocation(node.parent!)) {
|
||||
ctx.addFailureAtNode(node, Rule.POSTFIX_FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
visitIncrementDecrement(node: ts.UnaryExpression) {
|
||||
if (node.parent && (
|
||||
// Can be a statement
|
||||
node.parent.kind === ts.SyntaxKind.ExpressionStatement ||
|
||||
// Can be directly in a for-statement
|
||||
node.parent.kind === ts.SyntaxKind.ForStatement ||
|
||||
// Can be in a comma operator in a for statement (`for (let a = 0, b = 10; a < b; a++, b--)`)
|
||||
node.parent.kind === ts.SyntaxKind.BinaryExpression &&
|
||||
(<ts.BinaryExpression>node.parent).operatorToken.kind === ts.SyntaxKind.CommaToken &&
|
||||
node.parent.parent.kind === ts.SyntaxKind.ForStatement)) {
|
||||
return;
|
||||
}
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.POSTFIX_FAILURE_STRING));
|
||||
}
|
||||
}
|
||||
|
||||
function isAllowedLocation(node: ts.Node): boolean {
|
||||
switch (node.kind) {
|
||||
// Can be a statement
|
||||
case ts.SyntaxKind.ExpressionStatement:
|
||||
return true;
|
||||
|
||||
// Can be directly in a for-statement
|
||||
case ts.SyntaxKind.ForStatement:
|
||||
return true;
|
||||
|
||||
// Can be in a comma operator in a for statement (`for (let a = 0, b = 10; a < b; a++, b--)`)
|
||||
case ts.SyntaxKind.BinaryExpression:
|
||||
return (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.CommaToken &&
|
||||
node.parent!.kind === ts.SyntaxKind.ForStatement;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static TRAILING_FAILURE_STRING = "Excess trailing whitespace found around type assertion.";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new TypeAssertionWhitespaceWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class TypeAssertionWhitespaceWalker extends Lint.RuleWalker {
|
||||
public visitNode(node: ts.Node) {
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
ts.forEachChild(ctx.sourceFile, recur);
|
||||
function recur(node: ts.Node) {
|
||||
if (node.kind === ts.SyntaxKind.TypeAssertionExpression) {
|
||||
const refined = node as ts.TypeAssertion;
|
||||
const leftSideWhitespaceStart = refined.type.getEnd() + 1;
|
||||
const rightSideWhitespaceEnd = refined.expression.getStart();
|
||||
if (leftSideWhitespaceStart !== rightSideWhitespaceEnd) {
|
||||
this.addFailure(this.createFailure(leftSideWhitespaceStart, rightSideWhitespaceEnd, Rule.TRAILING_FAILURE_STRING));
|
||||
ctx.addFailure(leftSideWhitespaceStart, rightSideWhitespaceEnd, Rule.TRAILING_FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
super.visitNode(node);
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static LEADING_FAILURE_STRING = "No leading whitespace found on single-line object literal.";
|
||||
public static TRAILING_FAILURE_STRING = "No trailing whitespace found on single-line object literal.";
|
||||
@@ -9,34 +8,37 @@ export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static TRAILING_EXCESS_FAILURE_STRING = "Excess trailing whitespace found on single-line object literal.";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new ObjectLiteralSpaceWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class ObjectLiteralSpaceWalker extends Lint.RuleWalker {
|
||||
public visitNode(node: ts.Node) {
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
const { sourceFile } = ctx;
|
||||
ts.forEachChild(sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
|
||||
const literal = node as ts.ObjectLiteralExpression;
|
||||
const text = literal.getText();
|
||||
if (text.match(/^{[^\n]+}$/g)) {
|
||||
if (text.charAt(1) !== " ") {
|
||||
const failure = this.createFailure(node.pos, node.getWidth(), Rule.LEADING_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
if (text.charAt(2) === " ") {
|
||||
const failure = this.createFailure(node.pos + 2, 1, Rule.LEADING_EXCESS_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
if (text.charAt(text.length - 2) !== " ") {
|
||||
const failure = this.createFailure(node.pos, node.getWidth(), Rule.TRAILING_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
if (text.charAt(text.length - 3) === " ") {
|
||||
const failure = this.createFailure(node.pos + node.getWidth() - 3, 1, Rule.TRAILING_EXCESS_FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
check(node as ts.ObjectLiteralExpression);
|
||||
}
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
|
||||
function check(node: ts.ObjectLiteralExpression): void {
|
||||
const text = node.getText(sourceFile);
|
||||
if (!text.match(/^{[^\n]+}$/g)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (text.charAt(1) !== " ") {
|
||||
ctx.addFailureAtNode(node, Rule.LEADING_FAILURE_STRING);
|
||||
}
|
||||
if (text.charAt(2) === " ") {
|
||||
ctx.addFailureAt(node.pos + 2, 1, Rule.LEADING_EXCESS_FAILURE_STRING);
|
||||
}
|
||||
if (text.charAt(text.length - 2) !== " ") {
|
||||
ctx.addFailureAtNode(node, Rule.TRAILING_FAILURE_STRING);
|
||||
}
|
||||
if (text.charAt(text.length - 3) === " ") {
|
||||
ctx.addFailureAt(node.pos + node.getWidth() - 3, 1, Rule.TRAILING_EXCESS_FAILURE_STRING);
|
||||
}
|
||||
super.visitNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"strictNullChecks": true,
|
||||
"module": "commonjs",
|
||||
"outDir": "../../built/local/tslint"
|
||||
}
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
import * as Lint from "tslint/lib";
|
||||
import * as ts from "typescript";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static FAILURE_STRING = "The '|' and '&' operators must be surrounded by single spaces";
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new TypeOperatorSpacingWalker(sourceFile, this.getOptions()));
|
||||
return this.applyWithFunction(sourceFile, walk);
|
||||
}
|
||||
}
|
||||
|
||||
class TypeOperatorSpacingWalker extends Lint.RuleWalker {
|
||||
public visitNode(node: ts.Node) {
|
||||
function walk(ctx: Lint.WalkContext<void>): void {
|
||||
const { sourceFile } = ctx;
|
||||
ts.forEachChild(sourceFile, recur);
|
||||
function recur(node: ts.Node): void {
|
||||
if (node.kind === ts.SyntaxKind.UnionType || node.kind === ts.SyntaxKind.IntersectionType) {
|
||||
const types = (<ts.UnionOrIntersectionTypeNode>node).types;
|
||||
let expectedStart = types[0].end + 2; // space, | or &
|
||||
for (let i = 1; i < types.length; i++) {
|
||||
const currentType = types[i];
|
||||
if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) {
|
||||
const sourceFile = currentType.getSourceFile();
|
||||
const previousTypeEndPos = sourceFile.getLineAndCharacterOfPosition(types[i - 1].end);
|
||||
const currentTypeStartPos = sourceFile.getLineAndCharacterOfPosition(currentType.pos);
|
||||
if (previousTypeEndPos.line === currentTypeStartPos.line) {
|
||||
const failure = this.createFailure(currentType.pos, currentType.getWidth(), Rule.FAILURE_STRING);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
expectedStart = currentType.end + 2;
|
||||
}
|
||||
check((node as ts.UnionOrIntersectionTypeNode).types);
|
||||
}
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
|
||||
function check(types: ts.TypeNode[]): void {
|
||||
let expectedStart = types[0].end + 2; // space, | or &
|
||||
for (let i = 1; i < types.length; i++) {
|
||||
const currentType = types[i];
|
||||
if (expectedStart !== currentType.pos || currentType.getLeadingTriviaWidth() !== 1) {
|
||||
const previousTypeEndPos = sourceFile.getLineAndCharacterOfPosition(types[i - 1].end);
|
||||
const currentTypeStartPos = sourceFile.getLineAndCharacterOfPosition(currentType.pos);
|
||||
if (previousTypeEndPos.line === currentTypeStartPos.line) {
|
||||
ctx.addFailureAtNode(currentType, Rule.FAILURE_STRING);
|
||||
}
|
||||
}
|
||||
expectedStart = currentType.end + 2;
|
||||
}
|
||||
super.visitNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
+291
-81
@@ -182,7 +182,7 @@ namespace ts {
|
||||
return bindSourceFile;
|
||||
|
||||
function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean {
|
||||
if (opts.alwaysStrict && !isDeclarationFile(file)) {
|
||||
if ((opts.alwaysStrict === undefined ? opts.strict : opts.alwaysStrict) && !isDeclarationFile(file)) {
|
||||
// bind in strict mode source files with alwaysStrict option
|
||||
return true;
|
||||
}
|
||||
@@ -259,12 +259,13 @@ namespace ts {
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return (<ExportAssignment>node).isExportEquals ? "export=" : "default";
|
||||
case SyntaxKind.BinaryExpression:
|
||||
switch (getSpecialPropertyAssignmentKind(node)) {
|
||||
switch (getSpecialPropertyAssignmentKind(node as BinaryExpression)) {
|
||||
case SpecialPropertyAssignmentKind.ModuleExports:
|
||||
// module.exports = ...
|
||||
return "export=";
|
||||
case SpecialPropertyAssignmentKind.ExportsProperty:
|
||||
case SpecialPropertyAssignmentKind.ThisProperty:
|
||||
case SpecialPropertyAssignmentKind.Property:
|
||||
// exports.x = ... or this.y = ...
|
||||
return ((node as BinaryExpression).left as PropertyAccessExpression).name.text;
|
||||
case SpecialPropertyAssignmentKind.PrototypeProperty:
|
||||
@@ -417,7 +418,7 @@ namespace ts {
|
||||
return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
else {
|
||||
return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes);
|
||||
return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -446,13 +447,13 @@ namespace ts {
|
||||
(symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) |
|
||||
(symbolFlags & SymbolFlags.Type ? SymbolFlags.ExportType : 0) |
|
||||
(symbolFlags & SymbolFlags.Namespace ? SymbolFlags.ExportNamespace : 0);
|
||||
const local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
|
||||
const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes);
|
||||
local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
|
||||
node.localSymbol = local;
|
||||
return local;
|
||||
}
|
||||
else {
|
||||
return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes);
|
||||
return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -669,6 +670,12 @@ namespace ts {
|
||||
case SyntaxKind.CallExpression:
|
||||
bindCallExpressionFlow(<CallExpression>node);
|
||||
break;
|
||||
case SyntaxKind.JSDocComment:
|
||||
bindJSDocComment(<JSDoc>node);
|
||||
break;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
bindJSDocTypedefTag(<JSDocTypedefTag>node);
|
||||
break;
|
||||
default:
|
||||
bindEachChild(node);
|
||||
break;
|
||||
@@ -696,6 +703,7 @@ namespace ts {
|
||||
function isNarrowableReference(expr: Expression): boolean {
|
||||
return expr.kind === SyntaxKind.Identifier ||
|
||||
expr.kind === SyntaxKind.ThisKeyword ||
|
||||
expr.kind === SyntaxKind.SuperKeyword ||
|
||||
expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
|
||||
}
|
||||
|
||||
@@ -956,6 +964,9 @@ namespace ts {
|
||||
const postLoopLabel = createBranchLabel();
|
||||
addAntecedent(preLoopLabel, currentFlow);
|
||||
currentFlow = preLoopLabel;
|
||||
if (node.kind === SyntaxKind.ForOfStatement) {
|
||||
bind(node.awaitModifier);
|
||||
}
|
||||
bind(node.expression);
|
||||
addAntecedent(postLoopLabel, currentFlow);
|
||||
bind(node.initializer);
|
||||
@@ -1045,7 +1056,35 @@ namespace ts {
|
||||
if (node.finallyBlock) {
|
||||
// in finally flow is combined from pre-try/flow from try/flow from catch
|
||||
// pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable
|
||||
addAntecedent(preFinallyLabel, preTryFlow);
|
||||
|
||||
// also for finally blocks we inject two extra edges into the flow graph.
|
||||
// first -> edge that connects pre-try flow with the label at the beginning of the finally block, it has lock associated with it
|
||||
// second -> edge that represents post-finally flow.
|
||||
// these edges are used in following scenario:
|
||||
// let a; (1)
|
||||
// try { a = someOperation(); (2)}
|
||||
// finally { (3) console.log(a) } (4)
|
||||
// (5) a
|
||||
|
||||
// flow graph for this case looks roughly like this (arrows show ):
|
||||
// (1-pre-try-flow) <--.. <-- (2-post-try-flow)
|
||||
// ^ ^
|
||||
// |*****(3-pre-finally-label) -----|
|
||||
// ^
|
||||
// |-- ... <-- (4-post-finally-label) <--- (5)
|
||||
// In case when we walk the flow starting from inside the finally block we want to take edge '*****' into account
|
||||
// since it ensures that finally is always reachable. However when we start outside the finally block and go through label (5)
|
||||
// then edge '*****' should be discarded because label 4 is only reachable if post-finally label-4 is reachable
|
||||
// Simply speaking code inside finally block is treated as reachable as pre-try-flow
|
||||
// since we conservatively assume that any line in try block can throw or return in which case we'll enter finally.
|
||||
// However code after finally is reachable only if control flow was not abrupted in try/catch or finally blocks - it should be composed from
|
||||
// final flows of these blocks without taking pre-try flow into account.
|
||||
//
|
||||
// extra edges that we inject allows to control this behavior
|
||||
// if when walking the flow we step on post-finally edge - we can mark matching pre-finally edge as locked so it will be skipped.
|
||||
const preFinallyFlow: PreFinallyFlow = { flags: FlowFlags.PreFinally, antecedent: preTryFlow, lock: {} };
|
||||
addAntecedent(preFinallyLabel, preFinallyFlow);
|
||||
|
||||
currentFlow = finishFlowLabel(preFinallyLabel);
|
||||
bind(node.finallyBlock);
|
||||
// if flow after finally is unreachable - keep it
|
||||
@@ -1061,6 +1100,11 @@ namespace ts {
|
||||
: unreachableFlow;
|
||||
}
|
||||
}
|
||||
if (!(currentFlow.flags & FlowFlags.Unreachable)) {
|
||||
const afterFinallyFlow: AfterFinallyFlow = { flags: FlowFlags.AfterFinally, antecedent: currentFlow };
|
||||
preFinallyFlow.lock = afterFinallyFlow;
|
||||
currentFlow = afterFinallyFlow;
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentFlow = finishFlowLabel(preFinallyLabel);
|
||||
@@ -1298,6 +1342,26 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindJSDocComment(node: JSDoc) {
|
||||
forEachChild(node, n => {
|
||||
if (n.kind !== SyntaxKind.JSDocTypedefTag) {
|
||||
bind(n);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bindJSDocTypedefTag(node: JSDocTypedefTag) {
|
||||
forEachChild(node, n => {
|
||||
// if the node has a fullName "A.B.C", that means symbol "C" was already bound
|
||||
// when we visit "fullName"; so when we visit the name "C" as the next child of
|
||||
// the jsDocTypedefTag, we should skip binding it.
|
||||
if (node.fullName && n === node.name && node.fullName.kind !== SyntaxKind.Identifier) {
|
||||
return;
|
||||
}
|
||||
bind(n);
|
||||
});
|
||||
}
|
||||
|
||||
function bindCallExpressionFlow(node: CallExpression) {
|
||||
// If the target of the call expression is a function expression or arrow function we have
|
||||
// an immediately invoked function expression (IIFE). Initialize the flowNode property to
|
||||
@@ -1331,6 +1395,7 @@ namespace ts {
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return ContainerFlags.IsContainer;
|
||||
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
@@ -1437,6 +1502,7 @@ namespace ts {
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
// Interface/Object-types always have their children added to the 'members' of
|
||||
// their container. They are only accessible through an instance of their
|
||||
// container, and are never in scope otherwise (even inside the body of the
|
||||
@@ -1479,7 +1545,7 @@ namespace ts {
|
||||
function declareSourceFileMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
|
||||
return isExternalModule(file)
|
||||
? declareModuleMember(node, symbolFlags, symbolExcludes)
|
||||
: declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes);
|
||||
: declareSymbol(file.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
|
||||
function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean {
|
||||
@@ -1512,7 +1578,7 @@ namespace ts {
|
||||
errorOnFirstToken(node, Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible);
|
||||
}
|
||||
if (isExternalModuleAugmentation(node)) {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
|
||||
declareModuleSymbol(node);
|
||||
}
|
||||
else {
|
||||
let pattern: Pattern | undefined;
|
||||
@@ -1534,12 +1600,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
const state = getModuleInstanceState(node);
|
||||
if (state === ModuleInstanceState.NonInstantiated) {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
|
||||
}
|
||||
else {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
|
||||
const state = declareModuleSymbol(node);
|
||||
if (state !== ModuleInstanceState.NonInstantiated) {
|
||||
if (node.symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum)) {
|
||||
// if module was already merged with some function, class or non-const enum
|
||||
// treat is a non-const-enum-only
|
||||
@@ -1560,6 +1622,15 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function declareModuleSymbol(node: ModuleDeclaration): ModuleInstanceState {
|
||||
const state = getModuleInstanceState(node);
|
||||
const instantiated = state !== ModuleInstanceState.NonInstantiated;
|
||||
declareSymbolAndAddToSymbolTable(node,
|
||||
instantiated ? SymbolFlags.ValueModule : SymbolFlags.NamespaceModule,
|
||||
instantiated ? SymbolFlags.ValueModuleExcludes : SymbolFlags.NamespaceModuleExcludes);
|
||||
return state;
|
||||
}
|
||||
|
||||
function bindFunctionOrConstructorType(node: SignatureDeclaration): void {
|
||||
// For a given function symbol "<...>(...) => T" we want to generate a symbol identical
|
||||
// to the one we would get for: { <...>(...): T }
|
||||
@@ -1621,6 +1692,14 @@ namespace ts {
|
||||
return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__object");
|
||||
}
|
||||
|
||||
function bindJsxAttributes(node: JsxAttributes) {
|
||||
return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, "__jsxAttributes");
|
||||
}
|
||||
|
||||
function bindJsxAttribute(node: JsxAttribute, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
|
||||
return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
|
||||
function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) {
|
||||
const symbol = createSymbol(symbolFlags, name);
|
||||
addDeclarationToSymbol(symbol, node, symbolFlags);
|
||||
@@ -1642,7 +1721,7 @@ namespace ts {
|
||||
blockScopeContainer.locals = createMap<Symbol>();
|
||||
addToContainerChain(blockScopeContainer);
|
||||
}
|
||||
declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes);
|
||||
declareSymbol(blockScopeContainer.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1776,7 +1855,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkStrictModeNumericLiteral(node: NumericLiteral) {
|
||||
if (inStrictMode && node.isOctalLiteral) {
|
||||
if (inStrictMode && node.numericLiteralFlags & NumericLiteralFlags.Octal) {
|
||||
file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode));
|
||||
}
|
||||
}
|
||||
@@ -1822,6 +1901,20 @@ namespace ts {
|
||||
}
|
||||
node.parent = parent;
|
||||
const saveInStrictMode = inStrictMode;
|
||||
|
||||
// Even though in the AST the jsdoc @typedef node belongs to the current node,
|
||||
// its symbol might be in the same scope with the current node's symbol. Consider:
|
||||
//
|
||||
// /** @typedef {string | number} MyType */
|
||||
// function foo();
|
||||
//
|
||||
// Here the current node is "foo", which is a container, but the scope of "MyType" should
|
||||
// not be inside "foo". Therefore we always bind @typedef before bind the parent node,
|
||||
// and skip binding this tag later when binding all the other jsdoc tags.
|
||||
if (isInJavaScriptFile(node)) {
|
||||
bindJSDocTypedefTagIfAny(node);
|
||||
}
|
||||
|
||||
// First we bind declaration nodes to a symbol if possible. We'll both create a symbol
|
||||
// and then potentially add the symbol to an appropriate symbol table. Possible
|
||||
// destination symbol tables are:
|
||||
@@ -1856,6 +1949,27 @@ namespace ts {
|
||||
inStrictMode = saveInStrictMode;
|
||||
}
|
||||
|
||||
function bindJSDocTypedefTagIfAny(node: Node) {
|
||||
if (!node.jsDoc) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const jsDoc of node.jsDoc) {
|
||||
if (!jsDoc.tags) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const tag of jsDoc.tags) {
|
||||
if (tag.kind === SyntaxKind.JSDocTypedefTag) {
|
||||
const savedParent = parent;
|
||||
parent = jsDoc;
|
||||
bind(tag);
|
||||
parent = savedParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateStrictModeStatementList(statements: NodeArray<Statement>) {
|
||||
if (!inStrictMode) {
|
||||
for (const statement of statements) {
|
||||
@@ -1906,27 +2020,28 @@ namespace ts {
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.BinaryExpression:
|
||||
if (isInJavaScriptFile(node)) {
|
||||
const specialKind = getSpecialPropertyAssignmentKind(node);
|
||||
switch (specialKind) {
|
||||
case SpecialPropertyAssignmentKind.ExportsProperty:
|
||||
bindExportsPropertyAssignment(<BinaryExpression>node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.ModuleExports:
|
||||
bindModuleExportsAssignment(<BinaryExpression>node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.PrototypeProperty:
|
||||
bindPrototypePropertyAssignment(<BinaryExpression>node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.ThisProperty:
|
||||
bindThisPropertyAssignment(<BinaryExpression>node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.None:
|
||||
// Nothing to do
|
||||
break;
|
||||
default:
|
||||
Debug.fail("Unknown special property assignment kind");
|
||||
}
|
||||
const specialKind = getSpecialPropertyAssignmentKind(node as BinaryExpression);
|
||||
switch (specialKind) {
|
||||
case SpecialPropertyAssignmentKind.ExportsProperty:
|
||||
bindExportsPropertyAssignment(<BinaryExpression>node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.ModuleExports:
|
||||
bindModuleExportsAssignment(<BinaryExpression>node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.PrototypeProperty:
|
||||
bindPrototypePropertyAssignment(<BinaryExpression>node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.ThisProperty:
|
||||
bindThisPropertyAssignment(<BinaryExpression>node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.Property:
|
||||
bindStaticPropertyAssignment(<BinaryExpression>node);
|
||||
break;
|
||||
case SpecialPropertyAssignmentKind.None:
|
||||
// Nothing to do
|
||||
break;
|
||||
default:
|
||||
Debug.fail("Unknown special property assignment kind");
|
||||
}
|
||||
return checkStrictModeBinaryExpression(<BinaryExpression>node);
|
||||
case SyntaxKind.CatchClause:
|
||||
@@ -2042,6 +2157,12 @@ namespace ts {
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return bindModuleDeclaration(<ModuleDeclaration>node);
|
||||
|
||||
// Jsx-attributes
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return bindJsxAttributes(<JsxAttributes>node);
|
||||
case SyntaxKind.JsxAttribute:
|
||||
return bindJsxAttribute(<JsxAttribute>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
|
||||
// Imports and exports
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
case SyntaxKind.NamespaceImport:
|
||||
@@ -2169,7 +2290,42 @@ namespace ts {
|
||||
declareSymbol(file.symbol.exports, file.symbol, <PropertyAccessExpression>node.left, SymbolFlags.Property | SymbolFlags.Export, SymbolFlags.None);
|
||||
}
|
||||
|
||||
function isExportsOrModuleExportsOrAlias(node: Node): boolean {
|
||||
return isExportsIdentifier(node) ||
|
||||
isModuleExportsPropertyAccessExpression(node) ||
|
||||
isNameOfExportsOrModuleExportsAliasDeclaration(node);
|
||||
}
|
||||
|
||||
function isNameOfExportsOrModuleExportsAliasDeclaration(node: Node) {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
const symbol = container.locals.get((<Identifier>node).text);
|
||||
if (symbol && symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
|
||||
const declaration = symbol.valueDeclaration as VariableDeclaration;
|
||||
if (declaration.initializer) {
|
||||
return isExportsOrModuleExportsOrAliasOrAssignemnt(declaration.initializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isExportsOrModuleExportsOrAliasOrAssignemnt(node: Node): boolean {
|
||||
return isExportsOrModuleExportsOrAlias(node) ||
|
||||
(isAssignmentExpression(node, /*excludeCompoundAssignements*/ true) && (isExportsOrModuleExportsOrAliasOrAssignemnt(node.left) || isExportsOrModuleExportsOrAliasOrAssignemnt(node.right)));
|
||||
}
|
||||
|
||||
function bindModuleExportsAssignment(node: BinaryExpression) {
|
||||
// A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports'
|
||||
// is still pointing to 'module.exports'.
|
||||
// We do not want to consider this as 'export=' since a module can have only one of these.
|
||||
// Similarlly we do not want to treat 'module.exports = exports' as an 'export='.
|
||||
const assignedExpression = getRightMostAssignedExpression(node.right);
|
||||
if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) {
|
||||
// Mark it as a module in case there are no other exports in the file
|
||||
setCommonJsModuleIndicator(node);
|
||||
return;
|
||||
}
|
||||
|
||||
// 'module.exports = expr' assignment
|
||||
setCommonJsModuleIndicator(node);
|
||||
declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.Export | SymbolFlags.ValueModule, SymbolFlags.None);
|
||||
@@ -2177,23 +2333,30 @@ namespace ts {
|
||||
|
||||
function bindThisPropertyAssignment(node: BinaryExpression) {
|
||||
Debug.assert(isInJavaScriptFile(node));
|
||||
// Declare a 'member' if the container is an ES5 class or ES6 constructor
|
||||
if (container.kind === SyntaxKind.FunctionDeclaration || container.kind === SyntaxKind.FunctionExpression) {
|
||||
container.symbol.members = container.symbol.members || createMap<Symbol>();
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
}
|
||||
else if (container.kind === SyntaxKind.Constructor) {
|
||||
// this.foo assignment in a JavaScript class
|
||||
// Bind this property to the containing class
|
||||
const saveContainer = container;
|
||||
container = container.parent;
|
||||
const symbol = bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property, SymbolFlags.None);
|
||||
if (symbol) {
|
||||
// constructor-declared symbols can be overwritten by subsequent method declarations
|
||||
(symbol as Symbol).isReplaceableByMethod = true;
|
||||
}
|
||||
container = saveContainer;
|
||||
const container = getThisContainer(node, /*includeArrowFunctions*/ false);
|
||||
switch (container.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
// Declare a 'member' if the container is an ES5 class or ES6 constructor
|
||||
container.symbol.members = container.symbol.members || createMap<Symbol>();
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
break;
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
// this.foo assignment in a JavaScript class
|
||||
// Bind this property to the containing class
|
||||
const containingClass = container.parent;
|
||||
const symbol = declareSymbol(hasModifier(container, ModifierFlags.Static) ? containingClass.symbol.exports : containingClass.symbol.members, containingClass.symbol, node, SymbolFlags.Property, SymbolFlags.None);
|
||||
if (symbol) {
|
||||
// symbols declared through 'this' property assignements can be overwritten by subsequent method declarations
|
||||
(symbol as Symbol).isReplaceableByMethod = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2211,24 +2374,56 @@ namespace ts {
|
||||
constructorFunction.parent = classPrototype;
|
||||
classPrototype.parent = leftSideOfAssignment;
|
||||
|
||||
const funcSymbol = container.locals.get(constructorFunction.text);
|
||||
if (!funcSymbol || !(funcSymbol.flags & SymbolFlags.Function || isDeclarationOfFunctionExpression(funcSymbol))) {
|
||||
bindPropertyAssignment(constructorFunction.text, leftSideOfAssignment, /*isPrototypeProperty*/ true);
|
||||
}
|
||||
|
||||
function bindStaticPropertyAssignment(node: BinaryExpression) {
|
||||
// We saw a node of the form 'x.y = z'. Declare a 'member' y on x if x was a function.
|
||||
|
||||
// Look up the function in the local scope, since prototype assignments should
|
||||
// follow the function declaration
|
||||
const leftSideOfAssignment = node.left as PropertyAccessExpression;
|
||||
const target = leftSideOfAssignment.expression as Identifier;
|
||||
|
||||
// Fix up parent pointers since we're going to use these nodes before we bind into them
|
||||
leftSideOfAssignment.parent = node;
|
||||
target.parent = leftSideOfAssignment;
|
||||
|
||||
if (isNameOfExportsOrModuleExportsAliasDeclaration(target)) {
|
||||
// This can be an alias for the 'exports' or 'module.exports' names, e.g.
|
||||
// var util = module.exports;
|
||||
// util.property = function ...
|
||||
bindExportsPropertyAssignment(node);
|
||||
}
|
||||
else {
|
||||
bindPropertyAssignment(target.text, leftSideOfAssignment, /*isPrototypeProperty*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
function bindPropertyAssignment(functionName: string, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) {
|
||||
let targetSymbol = container.locals.get(functionName);
|
||||
|
||||
if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) {
|
||||
targetSymbol = (targetSymbol.valueDeclaration as VariableDeclaration).initializer.symbol;
|
||||
}
|
||||
|
||||
if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up the members collection if it doesn't exist already
|
||||
if (!funcSymbol.members) {
|
||||
funcSymbol.members = createMap<Symbol>();
|
||||
}
|
||||
const symbolTable = isPrototypeProperty ?
|
||||
(targetSymbol.members || (targetSymbol.members = createMap<Symbol>())) :
|
||||
(targetSymbol.exports || (targetSymbol.exports = createMap<Symbol>()));
|
||||
|
||||
// Declare the method/property
|
||||
declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
declareSymbol(symbolTable, targetSymbol, propertyAccessExpression, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
}
|
||||
|
||||
function bindCallExpression(node: CallExpression) {
|
||||
// We're only inspecting call expressions to detect CommonJS modules, so we can skip
|
||||
// this check if we've already seen the module indicator
|
||||
if (!file.commonJsModuleIndicator && isRequireCall(node, /*checkArgumentIsStringLiteral*/false)) {
|
||||
if (!file.commonJsModuleIndicator && isRequireCall(node, /*checkArgumentIsStringLiteral*/ false)) {
|
||||
setCommonJsModuleIndicator(node);
|
||||
}
|
||||
}
|
||||
@@ -2326,7 +2521,7 @@ namespace ts {
|
||||
|
||||
function bindFunctionDeclaration(node: FunctionDeclaration) {
|
||||
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
if (isAsyncFunction(node)) {
|
||||
emitFlags |= NodeFlags.HasAsyncFunctions;
|
||||
}
|
||||
}
|
||||
@@ -2343,7 +2538,7 @@ namespace ts {
|
||||
|
||||
function bindFunctionExpression(node: FunctionExpression) {
|
||||
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
if (isAsyncFunction(node)) {
|
||||
emitFlags |= NodeFlags.HasAsyncFunctions;
|
||||
}
|
||||
}
|
||||
@@ -2357,7 +2552,7 @@ namespace ts {
|
||||
|
||||
function bindPropertyOrMethodOrAccessor(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
|
||||
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
if (isAsyncFunction(node)) {
|
||||
emitFlags |= NodeFlags.HasAsyncFunctions;
|
||||
}
|
||||
}
|
||||
@@ -2791,11 +2986,10 @@ namespace ts {
|
||||
|
||||
// An async method declaration is ES2017 syntax.
|
||||
if (hasModifier(node, ModifierFlags.Async)) {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
transformFlags |= node.asteriskToken ? TransformFlags.AssertESNext : TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// Currently, we only support generators that were originally async function bodies.
|
||||
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
|
||||
if (node.asteriskToken) {
|
||||
transformFlags |= TransformFlags.AssertGenerator;
|
||||
}
|
||||
|
||||
@@ -2861,7 +3055,7 @@ namespace ts {
|
||||
|
||||
// An async function declaration is ES2017 syntax.
|
||||
if (modifierFlags & ModifierFlags.Async) {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
transformFlags |= node.asteriskToken ? TransformFlags.AssertESNext : TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// function declarations with object rest destructuring are ES Next syntax
|
||||
@@ -2881,7 +3075,7 @@ namespace ts {
|
||||
// down-level generator.
|
||||
// Currently we do not support transforming any other generator fucntions
|
||||
// down level.
|
||||
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
|
||||
if (node.asteriskToken) {
|
||||
transformFlags |= TransformFlags.AssertGenerator;
|
||||
}
|
||||
}
|
||||
@@ -2903,7 +3097,7 @@ namespace ts {
|
||||
|
||||
// An async function expression is ES2017 syntax.
|
||||
if (hasModifier(node, ModifierFlags.Async)) {
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
transformFlags |= node.asteriskToken ? TransformFlags.AssertESNext : TransformFlags.AssertES2017;
|
||||
}
|
||||
|
||||
// function expressions with object rest destructuring are ES Next syntax
|
||||
@@ -2922,9 +3116,7 @@ namespace ts {
|
||||
// If a FunctionExpression is generator function and is the body of a
|
||||
// transformed async function, then this node can be transformed to a
|
||||
// down-level generator.
|
||||
// Currently we do not support transforming any other generator fucntions
|
||||
// down level.
|
||||
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
|
||||
if (node.asteriskToken) {
|
||||
transformFlags |= TransformFlags.AssertGenerator;
|
||||
}
|
||||
|
||||
@@ -3092,8 +3284,8 @@ namespace ts {
|
||||
switch (kind) {
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
// async/await is ES2017 syntax
|
||||
transformFlags |= TransformFlags.AssertES2017;
|
||||
// async/await is ES2017 syntax, but may be ESNext syntax (for async generators)
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2017;
|
||||
break;
|
||||
|
||||
case SyntaxKind.PublicKeyword:
|
||||
@@ -3118,16 +3310,13 @@ namespace ts {
|
||||
case SyntaxKind.JsxText:
|
||||
case SyntaxKind.JsxClosingElement:
|
||||
case SyntaxKind.JsxAttribute:
|
||||
case SyntaxKind.JsxAttributes:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
case SyntaxKind.JsxExpression:
|
||||
// These nodes are Jsx syntax.
|
||||
transformFlags |= TransformFlags.AssertJsx;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
// for-of might be ESNext if it has a rest destructuring
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
// FALLTHROUGH
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
case SyntaxKind.TemplateHead:
|
||||
case SyntaxKind.TemplateMiddle:
|
||||
@@ -3141,9 +3330,30 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
break;
|
||||
|
||||
case SyntaxKind.StringLiteral:
|
||||
if ((<StringLiteral>node).hasExtendedUnicodeEscape) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.NumericLiteral:
|
||||
if ((<NumericLiteral>node).numericLiteralFlags & NumericLiteralFlags.BinaryOrOctalSpecifier) {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
// This node is either ES2015 syntax or ES2017 syntax (if it is a for-await-of).
|
||||
if ((<ForOfStatement>node).awaitModifier) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
break;
|
||||
|
||||
case SyntaxKind.YieldExpression:
|
||||
// This node is ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsYield;
|
||||
// This node is either ES2015 syntax (in a generator) or ES2017 syntax (in an async
|
||||
// generator).
|
||||
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2015 | TransformFlags.ContainsYield;
|
||||
break;
|
||||
|
||||
case SyntaxKind.AnyKeyword:
|
||||
|
||||
+3699
-1658
File diff suppressed because it is too large
Load Diff
+671
-422
File diff suppressed because it is too large
Load Diff
+118
-39
@@ -5,17 +5,17 @@ namespace ts {
|
||||
export interface CommentWriter {
|
||||
reset(): void;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
|
||||
setWriter(writer: EmitTextWriter): void;
|
||||
emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
|
||||
emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void;
|
||||
emitTrailingCommentsOfPosition(pos: number): void;
|
||||
emitLeadingCommentsOfPosition(pos: number): void;
|
||||
}
|
||||
|
||||
export function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
|
||||
const newLine = host.getNewLine();
|
||||
const { emitPos } = sourceMap;
|
||||
|
||||
export function createCommentWriter(printerOptions: PrinterOptions, emitPos: ((pos: number) => void) | undefined): CommentWriter {
|
||||
const extendedDiagnostics = printerOptions.extendedDiagnostics;
|
||||
const newLine = getNewLineCharacter(printerOptions);
|
||||
let writer: EmitTextWriter;
|
||||
let containerPos = -1;
|
||||
let containerEnd = -1;
|
||||
let declarationListContainerEnd = -1;
|
||||
@@ -24,35 +24,33 @@ namespace ts {
|
||||
let currentLineMap: number[];
|
||||
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[];
|
||||
let hasWrittenComment = false;
|
||||
let disabled: boolean = compilerOptions.removeComments;
|
||||
let disabled: boolean = printerOptions.removeComments;
|
||||
|
||||
return {
|
||||
reset,
|
||||
setWriter,
|
||||
setSourceFile,
|
||||
emitNodeWithComments,
|
||||
emitBodyWithDetachedComments,
|
||||
emitTrailingCommentsOfPosition,
|
||||
emitLeadingCommentsOfPosition,
|
||||
};
|
||||
|
||||
function emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
function emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
|
||||
if (disabled) {
|
||||
emitCallback(emitContext, node);
|
||||
emitCallback(hint, node);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
const { pos, end } = getCommentRange(node);
|
||||
const emitFlags = getEmitFlags(node);
|
||||
hasWrittenComment = false;
|
||||
|
||||
const emitNode = node.emitNode;
|
||||
const emitFlags = emitNode && emitNode.flags;
|
||||
const { pos, end } = emitNode && emitNode.commentRange || node;
|
||||
if ((pos < 0 && end < 0) || (pos === end)) {
|
||||
// Both pos and end are synthesized, so just emit the node without comments.
|
||||
if (emitFlags & EmitFlags.NoNestedComments) {
|
||||
disabled = true;
|
||||
emitCallback(emitContext, node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(emitContext, node);
|
||||
}
|
||||
emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback);
|
||||
}
|
||||
else {
|
||||
if (extendedDiagnostics) {
|
||||
@@ -92,17 +90,10 @@ namespace ts {
|
||||
performance.measure("commentTime", "preEmitNodeWithComment");
|
||||
}
|
||||
|
||||
if (emitFlags & EmitFlags.NoNestedComments) {
|
||||
disabled = true;
|
||||
emitCallback(emitContext, node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(emitContext, node);
|
||||
}
|
||||
emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback);
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("beginEmitNodeWithComment");
|
||||
performance.mark("postEmitNodeWithComment");
|
||||
}
|
||||
|
||||
// Restore previous container state.
|
||||
@@ -117,12 +108,88 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "beginEmitNodeWithComment");
|
||||
performance.measure("commentTime", "postEmitNodeWithComment");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitNodeWithSynthesizedComments(hint: EmitHint, node: Node, emitNode: EmitNode, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
|
||||
const leadingComments = emitNode && emitNode.leadingComments;
|
||||
if (some(leadingComments)) {
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("preEmitNodeWithSynthesizedComments");
|
||||
}
|
||||
|
||||
forEach(leadingComments, emitLeadingSynthesizedComment);
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "preEmitNodeWithSynthesizedComments");
|
||||
}
|
||||
}
|
||||
|
||||
emitNodeWithNestedComments(hint, node, emitFlags, emitCallback);
|
||||
|
||||
const trailingComments = emitNode && emitNode.trailingComments;
|
||||
if (some(trailingComments)) {
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("postEmitNodeWithSynthesizedComments");
|
||||
}
|
||||
|
||||
forEach(trailingComments, emitTrailingSynthesizedComment);
|
||||
|
||||
if (extendedDiagnostics) {
|
||||
performance.measure("commentTime", "postEmitNodeWithSynthesizedComments");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitLeadingSynthesizedComment(comment: SynthesizedComment) {
|
||||
if (comment.kind === SyntaxKind.SingleLineCommentTrivia) {
|
||||
writer.writeLine();
|
||||
}
|
||||
writeSynthesizedComment(comment);
|
||||
if (comment.hasTrailingNewLine || comment.kind === SyntaxKind.SingleLineCommentTrivia) {
|
||||
writer.writeLine();
|
||||
}
|
||||
else {
|
||||
writer.write(" ");
|
||||
}
|
||||
}
|
||||
|
||||
function emitTrailingSynthesizedComment(comment: SynthesizedComment) {
|
||||
if (!writer.isAtStartOfLine()) {
|
||||
writer.write(" ");
|
||||
}
|
||||
writeSynthesizedComment(comment);
|
||||
if (comment.hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
|
||||
function writeSynthesizedComment(comment: SynthesizedComment) {
|
||||
const text = formatSynthesizedComment(comment);
|
||||
const lineMap = comment.kind === SyntaxKind.MultiLineCommentTrivia ? computeLineStarts(text) : undefined;
|
||||
writeCommentRange(text, lineMap, writer, 0, text.length, newLine);
|
||||
}
|
||||
|
||||
function formatSynthesizedComment(comment: SynthesizedComment) {
|
||||
return comment.kind === SyntaxKind.MultiLineCommentTrivia
|
||||
? `/*${comment.text}*/`
|
||||
: `//${comment.text}`;
|
||||
}
|
||||
|
||||
function emitNodeWithNestedComments(hint: EmitHint, node: Node, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
|
||||
if (emitFlags & EmitFlags.NoNestedComments) {
|
||||
disabled = true;
|
||||
emitCallback(hint, node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(hint, node);
|
||||
}
|
||||
}
|
||||
|
||||
function emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) {
|
||||
if (extendedDiagnostics) {
|
||||
performance.mark("preEmitBodyWithDetachedComments");
|
||||
@@ -198,9 +265,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
|
||||
emitPos(commentPos);
|
||||
if (emitPos) emitPos(commentPos);
|
||||
writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine);
|
||||
emitPos(commentEnd);
|
||||
if (emitPos) emitPos(commentEnd);
|
||||
|
||||
if (hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
@@ -210,6 +277,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitLeadingCommentsOfPosition(pos: number) {
|
||||
if (disabled || pos === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitLeadingComments(pos, /*isEmittedNode*/ true);
|
||||
}
|
||||
|
||||
function emitTrailingComments(pos: number) {
|
||||
forEachTrailingCommentToEmit(pos, emitTrailingComment);
|
||||
}
|
||||
@@ -220,9 +295,9 @@ namespace ts {
|
||||
writer.write(" ");
|
||||
}
|
||||
|
||||
emitPos(commentPos);
|
||||
if (emitPos) emitPos(commentPos);
|
||||
writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine);
|
||||
emitPos(commentEnd);
|
||||
if (emitPos) emitPos(commentEnd);
|
||||
|
||||
if (hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
@@ -248,9 +323,9 @@ namespace ts {
|
||||
function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
|
||||
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
|
||||
|
||||
emitPos(commentPos);
|
||||
if (emitPos) emitPos(commentPos);
|
||||
writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine);
|
||||
emitPos(commentEnd);
|
||||
if (emitPos) emitPos(commentEnd);
|
||||
|
||||
if (hasTrailingNewLine) {
|
||||
writer.writeLine();
|
||||
@@ -286,6 +361,10 @@ namespace ts {
|
||||
detachedCommentsInfo = undefined;
|
||||
}
|
||||
|
||||
function setWriter(output: EmitTextWriter): void {
|
||||
writer = output;
|
||||
}
|
||||
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
currentSourceFile = sourceFile;
|
||||
currentText = currentSourceFile.text;
|
||||
@@ -323,16 +402,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
function writeComment(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) {
|
||||
emitPos(commentPos);
|
||||
if (emitPos) emitPos(commentPos);
|
||||
writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine);
|
||||
emitPos(commentEnd);
|
||||
if (emitPos) emitPos(commentEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given comment is a triple-slash
|
||||
*
|
||||
* @return true if the comment is a triple-slash comment else false
|
||||
**/
|
||||
*/
|
||||
function isTripleSlashComment(commentPos: number, commentEnd: number) {
|
||||
// Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text
|
||||
// so that we don't end up computing comment string and doing match for all // comments
|
||||
|
||||
+98
-63
@@ -1,9 +1,9 @@
|
||||
/// <reference path="types.ts"/>
|
||||
/// <reference path="types.ts"/>
|
||||
/// <reference path="performance.ts" />
|
||||
|
||||
namespace ts {
|
||||
/** The version of the TypeScript compiler release */
|
||||
export const version = "2.2.0";
|
||||
export const version = "2.3.0";
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -24,11 +24,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
// More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times.
|
||||
export const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator() : undefined;
|
||||
export const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }) : undefined;
|
||||
// Intl is missing in Safari, and node 0.10 treats "a" as greater than "B".
|
||||
export const localeCompareIsCorrect = ts.collator && ts.collator.compare("a", "B") < 0;
|
||||
|
||||
/** Create a MapLike with good performance. */
|
||||
function createDictionaryObject<T>(): MapLike<T> {
|
||||
const map = Object.create(null); // tslint:disable-line:no-null-keyword
|
||||
const map = Object.create(/*prototype*/ null); // tslint:disable-line:no-null-keyword
|
||||
|
||||
// Using 'delete' on an object causes V8 to put the object in dictionary mode.
|
||||
// This disables creation of hidden classes, which are expensive when an object is
|
||||
@@ -82,7 +84,7 @@ namespace ts {
|
||||
this.index++;
|
||||
return { value: this.selector(this.data, this.keys[index]), done: false };
|
||||
}
|
||||
return { value: undefined as never, done: true }
|
||||
return { value: undefined as never, done: true };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +140,7 @@ namespace ts {
|
||||
action(this.data[key], key);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {
|
||||
@@ -202,6 +204,10 @@ namespace ts {
|
||||
GreaterThan = 1
|
||||
}
|
||||
|
||||
export function length(array: any[]) {
|
||||
return array ? array.length : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through 'array' by index and performs the callback on each element of array until the callback
|
||||
* returns a truthy value, then returns that value.
|
||||
@@ -254,6 +260,16 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** Works like Array.prototype.findIndex, returning `-1` if no element satisfying the predicate is found. */
|
||||
export function findIndex<T>(array: T[], predicate: (element: T, index: number) => boolean): number {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (predicate(array[i], i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first truthy result of `callback`, or else fails.
|
||||
* This is like `forEach`, but never returns undefined.
|
||||
@@ -871,10 +887,20 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Shims `Array.from`. */
|
||||
export function arrayFrom<T>(iterator: Iterator<T>): T[] {
|
||||
const result: T[] = [];
|
||||
export function arrayFrom<T, U>(iterator: Iterator<T>, map: (t: T) => U): U[];
|
||||
export function arrayFrom<T>(iterator: Iterator<T>): T[];
|
||||
export function arrayFrom(iterator: Iterator<any>, map?: (t: any) => any): any[] {
|
||||
const result: any[] = [];
|
||||
for (let { value, done } = iterator.next(); !done; { value, done } = iterator.next()) {
|
||||
result.push(value);
|
||||
result.push(map ? map(value) : value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function convertToArray<T, U>(iterator: Iterator<T>, f: (value: T) => U) {
|
||||
const result: U[] = [];
|
||||
for (let { value, done } = iterator.next(); !done; { value, done } = iterator.next()) {
|
||||
result.push(f(value));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1247,9 +1273,12 @@ namespace ts {
|
||||
if (a === undefined) return Comparison.LessThan;
|
||||
if (b === undefined) return Comparison.GreaterThan;
|
||||
if (ignoreCase) {
|
||||
if (collator && String.prototype.localeCompare) {
|
||||
// accent means a ≠ b, a ≠ á, a = A
|
||||
const result = a.localeCompare(b, /*locales*/ undefined, { usage: "sort", sensitivity: "accent" });
|
||||
// Checking if "collator exists indicates that Intl is available.
|
||||
// We still have to check if "collator.compare" is correct. If it is not, use "String.localeComapre"
|
||||
if (collator) {
|
||||
const result = localeCompareIsCorrect ?
|
||||
collator.compare(a, b) :
|
||||
a.localeCompare(b, /*locales*/ undefined, { usage: "sort", sensitivity: "accent" }); // accent means a ≠ b, a ≠ á, a = A
|
||||
return result < 0 ? Comparison.LessThan : result > 0 ? Comparison.GreaterThan : Comparison.EqualTo;
|
||||
}
|
||||
|
||||
@@ -1331,7 +1360,7 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Returns length of path root (i.e. length of "/", "x:/", "//server/share/, file:///user/files")
|
||||
*/
|
||||
*/
|
||||
export function getRootLength(path: string): number {
|
||||
if (path.charCodeAt(0) === CharacterCodes.slash) {
|
||||
if (path.charCodeAt(1) !== CharacterCodes.slash) return 1;
|
||||
@@ -1715,7 +1744,19 @@ namespace ts {
|
||||
const singleAsteriskRegexFragmentFiles = "([^./]|(\\.(?!min\\.js$))?)*";
|
||||
const singleAsteriskRegexFragmentOther = "[^/]*";
|
||||
|
||||
export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude") {
|
||||
export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude"): string | undefined {
|
||||
const patterns = getRegularExpressionsForWildcards(specs, basePath, usage);
|
||||
if (!patterns || !patterns.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const pattern = patterns.map(pattern => `(${pattern})`).join("|");
|
||||
// If excluding, match "foo/bar/baz...", but if including, only allow "foo".
|
||||
const terminator = usage === "exclude" ? "($|/)" : "$";
|
||||
return `^(${pattern})${terminator}`;
|
||||
}
|
||||
|
||||
function getRegularExpressionsForWildcards(specs: string[], basePath: string, usage: "files" | "directories" | "exclude"): string[] | undefined {
|
||||
if (specs === undefined || specs.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1729,33 +1770,8 @@ namespace ts {
|
||||
*/
|
||||
const doubleAsteriskRegexFragment = usage === "exclude" ? "(/.+?)?" : "(/[^/.][^/]*)*?";
|
||||
|
||||
let pattern = "";
|
||||
let hasWrittenSubpattern = false;
|
||||
for (const spec of specs) {
|
||||
if (!spec) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const subPattern = getSubPatternFromSpec(spec, basePath, usage, singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter);
|
||||
if (subPattern === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasWrittenSubpattern) {
|
||||
pattern += "|";
|
||||
}
|
||||
|
||||
pattern += "(" + subPattern + ")";
|
||||
hasWrittenSubpattern = true;
|
||||
}
|
||||
|
||||
if (!pattern) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// If excluding, match "foo/bar/baz...", but if including, only allow "foo".
|
||||
const terminator = usage === "exclude" ? "($|/)" : "$";
|
||||
return `^(${pattern})${terminator}`;
|
||||
return flatMap(specs, spec =>
|
||||
spec && getSubPatternFromSpec(spec, basePath, usage, singleAsteriskRegexFragment, doubleAsteriskRegexFragment, replaceWildcardCharacter));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1850,6 +1866,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface FileMatcherPatterns {
|
||||
/** One pattern for each "include" spec. */
|
||||
includeFilePatterns: string[];
|
||||
/** One pattern matching one of any of the "include" specs. */
|
||||
includeFilePattern: string;
|
||||
includeDirectoryPattern: string;
|
||||
excludePattern: string;
|
||||
@@ -1862,6 +1881,7 @@ namespace ts {
|
||||
const absolutePath = combinePaths(currentDirectory, path);
|
||||
|
||||
return {
|
||||
includeFilePatterns: map(getRegularExpressionsForWildcards(includes, absolutePath, "files"), pattern => `^${pattern}$`),
|
||||
includeFilePattern: getRegularExpressionForWildcard(includes, absolutePath, "files"),
|
||||
includeDirectoryPattern: getRegularExpressionForWildcard(includes, absolutePath, "directories"),
|
||||
excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, "exclude"),
|
||||
@@ -1876,26 +1896,39 @@ namespace ts {
|
||||
const patterns = getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
|
||||
|
||||
const regexFlag = useCaseSensitiveFileNames ? "" : "i";
|
||||
const includeFileRegex = patterns.includeFilePattern && new RegExp(patterns.includeFilePattern, regexFlag);
|
||||
const includeFileRegexes = patterns.includeFilePatterns && patterns.includeFilePatterns.map(pattern => new RegExp(pattern, regexFlag));
|
||||
const includeDirectoryRegex = patterns.includeDirectoryPattern && new RegExp(patterns.includeDirectoryPattern, regexFlag);
|
||||
const excludeRegex = patterns.excludePattern && new RegExp(patterns.excludePattern, regexFlag);
|
||||
|
||||
const result: string[] = [];
|
||||
// Associate an array of results with each include regex. This keeps results in order of the "include" order.
|
||||
// If there are no "includes", then just put everything in results[0].
|
||||
const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]];
|
||||
|
||||
const comparer = useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive;
|
||||
for (const basePath of patterns.basePaths) {
|
||||
visitDirectory(basePath, combinePaths(currentDirectory, basePath));
|
||||
}
|
||||
return result;
|
||||
|
||||
return flatten(results);
|
||||
|
||||
function visitDirectory(path: string, absolutePath: string) {
|
||||
const { files, directories } = getFileSystemEntries(path);
|
||||
let { files, directories } = getFileSystemEntries(path);
|
||||
files = files.slice().sort(comparer);
|
||||
directories = directories.slice().sort(comparer);
|
||||
|
||||
for (const current of files) {
|
||||
const name = combinePaths(path, current);
|
||||
const absoluteName = combinePaths(absolutePath, current);
|
||||
if ((!extensions || fileExtensionIsAny(name, extensions)) &&
|
||||
(!includeFileRegex || includeFileRegex.test(absoluteName)) &&
|
||||
(!excludeRegex || !excludeRegex.test(absoluteName))) {
|
||||
result.push(name);
|
||||
if (extensions && !fileExtensionIsAny(name, extensions)) continue;
|
||||
if (excludeRegex && excludeRegex.test(absoluteName)) continue;
|
||||
if (!includeFileRegexes) {
|
||||
results[0].push(name);
|
||||
}
|
||||
else {
|
||||
const includeIndex = findIndex(includeFileRegexes, re => re.test(absoluteName));
|
||||
if (includeIndex !== -1) {
|
||||
results[includeIndex].push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1989,14 +2022,14 @@ namespace ts {
|
||||
export const supportedJavascriptExtensions = [".js", ".jsx"];
|
||||
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
|
||||
|
||||
export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: FileExtensionInfo[]): string[] {
|
||||
export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: JsFileExtensionInfo[]): string[] {
|
||||
const needAllExtensions = options && options.allowJs;
|
||||
if (!extraFileExtensions || extraFileExtensions.length === 0) {
|
||||
if (!extraFileExtensions || extraFileExtensions.length === 0 || !needAllExtensions) {
|
||||
return needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions;
|
||||
}
|
||||
const extensions = (needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions).slice(0);
|
||||
const extensions = allSupportedExtensions.slice(0);
|
||||
for (const extInfo of extraFileExtensions) {
|
||||
if (needAllExtensions || extInfo.scriptKind === ScriptKind.TS) {
|
||||
if (extensions.indexOf(extInfo.extension) === -1) {
|
||||
extensions.push(extInfo.extension);
|
||||
}
|
||||
}
|
||||
@@ -2011,7 +2044,7 @@ namespace ts {
|
||||
return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension));
|
||||
}
|
||||
|
||||
export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: FileExtensionInfo[]) {
|
||||
export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: JsFileExtensionInfo[]) {
|
||||
if (!fileName) { return false; }
|
||||
|
||||
for (const extension of getSupportedExtensions(compilerOptions, extraFileExtensions)) {
|
||||
@@ -2030,7 +2063,6 @@ namespace ts {
|
||||
export const enum ExtensionPriority {
|
||||
TypeScriptFiles = 0,
|
||||
DeclarationAndJavaScriptFiles = 2,
|
||||
Limit = 5,
|
||||
|
||||
Highest = TypeScriptFiles,
|
||||
Lowest = DeclarationAndJavaScriptFiles,
|
||||
@@ -2039,7 +2071,7 @@ namespace ts {
|
||||
export function getExtensionPriority(path: string, supportedExtensions: string[]): ExtensionPriority {
|
||||
for (let i = supportedExtensions.length - 1; i >= 0; i--) {
|
||||
if (fileExtensionIs(path, supportedExtensions[i])) {
|
||||
return adjustExtensionPriority(<ExtensionPriority>i);
|
||||
return adjustExtensionPriority(<ExtensionPriority>i, supportedExtensions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2051,27 +2083,26 @@ namespace ts {
|
||||
/**
|
||||
* Adjusts an extension priority to be the highest priority within the same range.
|
||||
*/
|
||||
export function adjustExtensionPriority(extensionPriority: ExtensionPriority): ExtensionPriority {
|
||||
export function adjustExtensionPriority(extensionPriority: ExtensionPriority, supportedExtensions: string[]): ExtensionPriority {
|
||||
if (extensionPriority < ExtensionPriority.DeclarationAndJavaScriptFiles) {
|
||||
return ExtensionPriority.TypeScriptFiles;
|
||||
}
|
||||
else if (extensionPriority < ExtensionPriority.Limit) {
|
||||
else if (extensionPriority < supportedExtensions.length) {
|
||||
return ExtensionPriority.DeclarationAndJavaScriptFiles;
|
||||
}
|
||||
else {
|
||||
return ExtensionPriority.Limit;
|
||||
}
|
||||
}
|
||||
return supportedExtensions.length;
|
||||
} }
|
||||
|
||||
/**
|
||||
* Gets the next lowest extension priority for a given priority.
|
||||
*/
|
||||
export function getNextLowestExtensionPriority(extensionPriority: ExtensionPriority): ExtensionPriority {
|
||||
export function getNextLowestExtensionPriority(extensionPriority: ExtensionPriority, supportedExtensions: string[]): ExtensionPriority {
|
||||
if (extensionPriority < ExtensionPriority.DeclarationAndJavaScriptFiles) {
|
||||
return ExtensionPriority.DeclarationAndJavaScriptFiles;
|
||||
}
|
||||
else {
|
||||
return ExtensionPriority.Limit;
|
||||
return supportedExtensions.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2331,4 +2362,8 @@ namespace ts {
|
||||
return Extension.Jsx;
|
||||
}
|
||||
}
|
||||
|
||||
export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) {
|
||||
return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,16 +32,18 @@ namespace ts {
|
||||
|
||||
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
|
||||
const declarationDiagnostics = createDiagnosticCollection();
|
||||
forEachExpectedEmitFile(host, getDeclarationDiagnosticsFromFile, targetSourceFile);
|
||||
forEachEmittedFile(host, getDeclarationDiagnosticsFromFile, targetSourceFile);
|
||||
return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined);
|
||||
|
||||
function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sources: SourceFile[], isBundledEmit: boolean) {
|
||||
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit, /*emitOnlyDtsFiles*/ false);
|
||||
function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
|
||||
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sourceFileOrBundle, /*emitOnlyDtsFiles*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string,
|
||||
sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean): DeclarationEmit {
|
||||
sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean): DeclarationEmit {
|
||||
const sourceFiles = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle.sourceFiles : [sourceFileOrBundle];
|
||||
const isBundledEmit = sourceFileOrBundle.kind === SyntaxKind.Bundle;
|
||||
const newLine = host.getNewLine();
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
|
||||
@@ -188,6 +190,7 @@ namespace ts {
|
||||
const writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
|
||||
writer.trackSymbol = trackSymbol;
|
||||
writer.reportInaccessibleThisError = reportInaccessibleThisError;
|
||||
writer.reportIllegalExtends = reportIllegalExtends;
|
||||
writer.writeKeyword = writer.write;
|
||||
writer.writeOperator = writer.write;
|
||||
writer.writePunctuation = writer.write;
|
||||
@@ -311,6 +314,14 @@ namespace ts {
|
||||
recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning));
|
||||
}
|
||||
|
||||
function reportIllegalExtends() {
|
||||
if (errorNameNode) {
|
||||
reportedDeclarationError = true;
|
||||
emitterDiagnostics.add(createDiagnosticForNode(errorNameNode, Diagnostics.extends_clause_of_exported_class_0_refers_to_a_type_whose_name_cannot_be_referenced,
|
||||
declarationNameToString(errorNameNode)));
|
||||
}
|
||||
}
|
||||
|
||||
function reportInaccessibleThisError() {
|
||||
if (errorNameNode) {
|
||||
reportedDeclarationError = true;
|
||||
@@ -322,13 +333,20 @@ namespace ts {
|
||||
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, type: TypeNode, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
|
||||
writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
|
||||
write(": ");
|
||||
if (type) {
|
||||
|
||||
// use the checker's type, not the declared type,
|
||||
// for non-optional initialized parameters that aren't a parameter property
|
||||
const shouldUseResolverType = declaration.kind === SyntaxKind.Parameter &&
|
||||
resolver.isRequiredInitializedParameter(declaration as ParameterDeclaration);
|
||||
if (type && !shouldUseResolverType) {
|
||||
// Write the type
|
||||
emitType(type);
|
||||
}
|
||||
else {
|
||||
errorNameNode = declaration.name;
|
||||
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
|
||||
const format = TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue |
|
||||
(shouldUseResolverType ? TypeFormatFlags.AddUndefined : 0);
|
||||
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, format, writer);
|
||||
errorNameNode = undefined;
|
||||
}
|
||||
}
|
||||
@@ -572,7 +590,7 @@ namespace ts {
|
||||
currentIdentifiers = node.identifiers;
|
||||
isCurrentFileExternalModule = isExternalModule(node);
|
||||
enclosingDeclaration = node;
|
||||
emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, true /* remove comments */);
|
||||
emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, /*removeComents*/ true);
|
||||
emitLines(node.statements);
|
||||
}
|
||||
|
||||
@@ -1001,6 +1019,23 @@ namespace ts {
|
||||
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.constraint, getTypeParameterConstraintVisibilityError);
|
||||
}
|
||||
}
|
||||
if (node.default && !isPrivateMethodTypeParameter(node)) {
|
||||
write(" = ");
|
||||
if (node.parent.kind === SyntaxKind.FunctionType ||
|
||||
node.parent.kind === SyntaxKind.ConstructorType ||
|
||||
(node.parent.parent && node.parent.parent.kind === SyntaxKind.TypeLiteral)) {
|
||||
Debug.assert(node.parent.kind === SyntaxKind.MethodDeclaration ||
|
||||
node.parent.kind === SyntaxKind.MethodSignature ||
|
||||
node.parent.kind === SyntaxKind.FunctionType ||
|
||||
node.parent.kind === SyntaxKind.ConstructorType ||
|
||||
node.parent.kind === SyntaxKind.CallSignature ||
|
||||
node.parent.kind === SyntaxKind.ConstructSignature);
|
||||
emitType(node.default);
|
||||
}
|
||||
else {
|
||||
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.default, getTypeParameterConstraintVisibilityError);
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeParameterConstraintVisibilityError(): SymbolAccessibilityDiagnostic {
|
||||
// Type parameter constraints are named by user so we should always be able to name it
|
||||
@@ -1062,7 +1097,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitHeritageClause(typeReferences: ExpressionWithTypeArguments[], isImplementsList: boolean) {
|
||||
function emitHeritageClause(className: Identifier, typeReferences: ExpressionWithTypeArguments[], isImplementsList: boolean) {
|
||||
if (typeReferences) {
|
||||
write(isImplementsList ? " implements " : " extends ");
|
||||
emitCommaList(typeReferences, emitTypeOfTypeReference);
|
||||
@@ -1077,7 +1112,9 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError;
|
||||
errorNameNode = className;
|
||||
resolver.writeBaseConstructorTypeOfClass(<ClassLikeDeclaration>enclosingDeclaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
|
||||
errorNameNode = undefined;
|
||||
}
|
||||
|
||||
function getHeritageClauseVisibilityError(): SymbolAccessibilityDiagnostic {
|
||||
@@ -1087,11 +1124,11 @@ namespace ts {
|
||||
// Class or Interface implemented/extended is inaccessible
|
||||
diagnosticMessage = isImplementsList ?
|
||||
Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 :
|
||||
Diagnostics.Extends_clause_of_exported_class_0_has_or_is_using_private_name_1;
|
||||
Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1;
|
||||
}
|
||||
else {
|
||||
// interface is inaccessible
|
||||
diagnosticMessage = Diagnostics.Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1;
|
||||
diagnosticMessage = Diagnostics.extends_clause_of_exported_interface_0_has_or_is_using_private_name_1;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -1127,9 +1164,10 @@ namespace ts {
|
||||
emitTypeParameters(node.typeParameters);
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
|
||||
if (baseTypeNode) {
|
||||
emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
|
||||
node.name;
|
||||
emitHeritageClause(node.name, [baseTypeNode], /*isImplementsList*/ false);
|
||||
}
|
||||
emitHeritageClause(getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true);
|
||||
emitHeritageClause(node.name, getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true);
|
||||
write(" {");
|
||||
writeLine();
|
||||
increaseIndent();
|
||||
@@ -1151,7 +1189,7 @@ namespace ts {
|
||||
emitTypeParameters(node.typeParameters);
|
||||
const interfaceExtendsTypes = filter(getInterfaceBaseTypeNodes(node), base => isEntityNameExpression(base.expression));
|
||||
if (interfaceExtendsTypes && interfaceExtendsTypes.length) {
|
||||
emitHeritageClause(interfaceExtendsTypes, /*isImplementsList*/ false);
|
||||
emitHeritageClause(node.name, interfaceExtendsTypes, /*isImplementsList*/ false);
|
||||
}
|
||||
write(" {");
|
||||
writeLine();
|
||||
@@ -1788,7 +1826,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
// Get the declaration file path
|
||||
forEachExpectedEmitFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles);
|
||||
forEachEmittedFile(host, getDeclFileName, referencedFile, emitOnlyDtsFiles);
|
||||
}
|
||||
|
||||
if (declFileName) {
|
||||
@@ -1803,8 +1841,9 @@ namespace ts {
|
||||
}
|
||||
return addedBundledEmitReference;
|
||||
|
||||
function getDeclFileName(emitFileNames: EmitFileNames, _sourceFiles: SourceFile[], isBundledEmit: boolean) {
|
||||
function getDeclFileName(emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
|
||||
// Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path
|
||||
const isBundledEmit = sourceFileOrBundle.kind === SyntaxKind.Bundle;
|
||||
if (isBundledEmit && !addBundledFileReference) {
|
||||
return;
|
||||
}
|
||||
@@ -1817,10 +1856,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) {
|
||||
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles);
|
||||
export function writeDeclarationFile(declarationFilePath: string, sourceFileOrBundle: SourceFile | Bundle, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) {
|
||||
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFileOrBundle, emitOnlyDtsFiles);
|
||||
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit;
|
||||
if (!emitSkipped) {
|
||||
const sourceFiles = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle.sourceFiles : [sourceFileOrBundle];
|
||||
const declarationOutput = emitDeclarationResult.referencesOutput
|
||||
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
|
||||
writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM, sourceFiles);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
{
|
||||
"Unterminated string literal.": {
|
||||
"category": "Error",
|
||||
"code": 1002
|
||||
@@ -175,15 +175,15 @@
|
||||
"category": "Error",
|
||||
"code": 1057
|
||||
},
|
||||
"Operand for 'await' does not have a valid callable 'then' member.": {
|
||||
"Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.": {
|
||||
"category": "Error",
|
||||
"code": 1058
|
||||
},
|
||||
"Return expression in async function does not have a valid callable 'then' member.": {
|
||||
"A promise must have a 'then' method.": {
|
||||
"category": "Error",
|
||||
"code": 1059
|
||||
},
|
||||
"Expression body for async arrow function does not have a valid callable 'then' member.": {
|
||||
"The first parameter of the 'then' method of a promise must be a callback.": {
|
||||
"category": "Error",
|
||||
"code": 1060
|
||||
},
|
||||
@@ -191,7 +191,7 @@
|
||||
"category": "Error",
|
||||
"code": 1061
|
||||
},
|
||||
"{0} is referenced directly or indirectly in the fulfillment callback of its own 'then' method.": {
|
||||
"Type is referenced directly or indirectly in the fulfillment callback of its own 'then' method.": {
|
||||
"category": "Error",
|
||||
"code": 1062
|
||||
},
|
||||
@@ -291,6 +291,10 @@
|
||||
"category": "Error",
|
||||
"code": 1102
|
||||
},
|
||||
"A 'for-await-of' statement is only allowed within an async function or async generator.": {
|
||||
"category": "Error",
|
||||
"code": 1103
|
||||
},
|
||||
"A 'continue' statement can only be used within an enclosing iteration statement.": {
|
||||
"category": "Error",
|
||||
"code": 1104
|
||||
@@ -319,7 +323,7 @@
|
||||
"category": "Error",
|
||||
"code": 1113
|
||||
},
|
||||
"Duplicate label '{0}'": {
|
||||
"Duplicate label '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 1114
|
||||
},
|
||||
@@ -447,7 +451,7 @@
|
||||
"category": "Error",
|
||||
"code": 1148
|
||||
},
|
||||
"File name '{0}' differs from already included file name '{1}' only in casing": {
|
||||
"File name '{0}' differs from already included file name '{1}' only in casing.": {
|
||||
"category": "Error",
|
||||
"code": 1149
|
||||
},
|
||||
@@ -455,7 +459,7 @@
|
||||
"category": "Error",
|
||||
"code": 1150
|
||||
},
|
||||
"'const' declarations must be initialized": {
|
||||
"'const' declarations must be initialized.": {
|
||||
"category": "Error",
|
||||
"code": 1155
|
||||
},
|
||||
@@ -651,11 +655,11 @@
|
||||
"category": "Error",
|
||||
"code": 1210
|
||||
},
|
||||
"A class declaration without the 'default' modifier must have a name": {
|
||||
"A class declaration without the 'default' modifier must have a name.": {
|
||||
"category": "Error",
|
||||
"code": 1211
|
||||
},
|
||||
"Identifier expected. '{0}' is a reserved word in strict mode": {
|
||||
"Identifier expected. '{0}' is a reserved word in strict mode.": {
|
||||
"category": "Error",
|
||||
"code": 1212
|
||||
},
|
||||
@@ -671,6 +675,10 @@
|
||||
"category": "Error",
|
||||
"code": 1215
|
||||
},
|
||||
"Identifier expected. '__esModule' is reserved as an exported marker when transforming ECMAScript modules.": {
|
||||
"category": "Error",
|
||||
"code": 1216
|
||||
},
|
||||
"Export assignment is not supported when '--module' flag is 'system'.": {
|
||||
"category": "Error",
|
||||
"code": 1218
|
||||
@@ -1103,7 +1111,7 @@
|
||||
"category": "Error",
|
||||
"code": 2360
|
||||
},
|
||||
"The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter": {
|
||||
"The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter.": {
|
||||
"category": "Error",
|
||||
"code": 2361
|
||||
},
|
||||
@@ -1127,7 +1135,7 @@
|
||||
"category": "Error",
|
||||
"code": 2366
|
||||
},
|
||||
"Type parameter name cannot be '{0}'": {
|
||||
"Type parameter name cannot be '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2368
|
||||
},
|
||||
@@ -1287,7 +1295,7 @@
|
||||
"category": "Error",
|
||||
"code": 2408
|
||||
},
|
||||
"Return type of constructor signature must be assignable to the instance type of the class": {
|
||||
"Return type of constructor signature must be assignable to the instance type of the class.": {
|
||||
"category": "Error",
|
||||
"code": 2409
|
||||
},
|
||||
@@ -1307,7 +1315,7 @@
|
||||
"category": "Error",
|
||||
"code": 2413
|
||||
},
|
||||
"Class name cannot be '{0}'": {
|
||||
"Class name cannot be '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2414
|
||||
},
|
||||
@@ -1343,7 +1351,7 @@
|
||||
"category": "Error",
|
||||
"code": 2426
|
||||
},
|
||||
"Interface name cannot be '{0}'": {
|
||||
"Interface name cannot be '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2427
|
||||
},
|
||||
@@ -1355,7 +1363,7 @@
|
||||
"category": "Error",
|
||||
"code": 2430
|
||||
},
|
||||
"Enum name cannot be '{0}'": {
|
||||
"Enum name cannot be '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2431
|
||||
},
|
||||
@@ -1363,11 +1371,11 @@
|
||||
"category": "Error",
|
||||
"code": 2432
|
||||
},
|
||||
"A namespace declaration cannot be in a different file from a class or function with which it is merged": {
|
||||
"A namespace declaration cannot be in a different file from a class or function with which it is merged.": {
|
||||
"category": "Error",
|
||||
"code": 2433
|
||||
},
|
||||
"A namespace declaration cannot be located prior to a class or function with which it is merged": {
|
||||
"A namespace declaration cannot be located prior to a class or function with which it is merged.": {
|
||||
"category": "Error",
|
||||
"code": 2434
|
||||
},
|
||||
@@ -1379,11 +1387,11 @@
|
||||
"category": "Error",
|
||||
"code": 2436
|
||||
},
|
||||
"Module '{0}' is hidden by a local declaration with the same name": {
|
||||
"Module '{0}' is hidden by a local declaration with the same name.": {
|
||||
"category": "Error",
|
||||
"code": 2437
|
||||
},
|
||||
"Import name cannot be '{0}'": {
|
||||
"Import name cannot be '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2438
|
||||
},
|
||||
@@ -1391,7 +1399,7 @@
|
||||
"category": "Error",
|
||||
"code": 2439
|
||||
},
|
||||
"Import declaration conflicts with local declaration of '{0}'": {
|
||||
"Import declaration conflicts with local declaration of '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2440
|
||||
},
|
||||
@@ -1427,6 +1435,14 @@
|
||||
"category": "Error",
|
||||
"code": 2448
|
||||
},
|
||||
"Class '{0}' used before its declaration.": {
|
||||
"category": "Error",
|
||||
"code": 2449
|
||||
},
|
||||
"Enum '{0}' used before its declaration.": {
|
||||
"category": "Error",
|
||||
"code": 2450
|
||||
},
|
||||
"Cannot redeclare block-scoped variable '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2451
|
||||
@@ -1451,7 +1467,7 @@
|
||||
"category": "Error",
|
||||
"code": 2456
|
||||
},
|
||||
"Type alias name cannot be '{0}'": {
|
||||
"Type alias name cannot be '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2457
|
||||
},
|
||||
@@ -1471,7 +1487,7 @@
|
||||
"category": "Error",
|
||||
"code": 2461
|
||||
},
|
||||
"A rest element must be last in a destructuring pattern": {
|
||||
"A rest element must be last in a destructuring pattern.": {
|
||||
"category": "Error",
|
||||
"code": 2462
|
||||
},
|
||||
@@ -1555,7 +1571,7 @@
|
||||
"category": "Error",
|
||||
"code": 2483
|
||||
},
|
||||
"Export declaration conflicts with exported declaration of '{0}'": {
|
||||
"Export declaration conflicts with exported declaration of '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2484
|
||||
},
|
||||
@@ -1579,7 +1595,7 @@
|
||||
"category": "Error",
|
||||
"code": 2491
|
||||
},
|
||||
"Cannot redeclare identifier '{0}' in catch clause": {
|
||||
"Cannot redeclare identifier '{0}' in catch clause.": {
|
||||
"category": "Error",
|
||||
"code": 2492
|
||||
},
|
||||
@@ -1627,6 +1643,10 @@
|
||||
"category": "Error",
|
||||
"code": 2503
|
||||
},
|
||||
"Type must have a '[Symbol.asyncIterator]()' method that returns an async iterator.": {
|
||||
"category": "Error",
|
||||
"code": 2504
|
||||
},
|
||||
"A generator cannot have a 'void' type annotation.": {
|
||||
"category": "Error",
|
||||
"code": 2505
|
||||
@@ -1683,6 +1703,10 @@
|
||||
"category": "Error",
|
||||
"code": 2518
|
||||
},
|
||||
"An async iterator must have a 'next()' method.": {
|
||||
"category": "Error",
|
||||
"code": 2519
|
||||
},
|
||||
"Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions.": {
|
||||
"category": "Error",
|
||||
"code": 2520
|
||||
@@ -1783,6 +1807,30 @@
|
||||
"category": "Error",
|
||||
"code": 2544
|
||||
},
|
||||
"A mixin class must have a constructor with a single rest parameter of type 'any[]'.": {
|
||||
"category": "Error",
|
||||
"code": 2545
|
||||
},
|
||||
"Property '{0}' has conflicting declarations and is inaccessible in type '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2546
|
||||
},
|
||||
"The type returned by the 'next()' method of an async iterator must be a promise for a type with a 'value' property.": {
|
||||
"category": "Error",
|
||||
"code": 2547
|
||||
},
|
||||
"Type '{0}' is not an array type or does not have a '[Symbol.iterator]()' method that returns an iterator.": {
|
||||
"category": "Error",
|
||||
"code": 2548
|
||||
},
|
||||
"Type '{0}' is not an array type or a string type or does not have a '[Symbol.iterator]()' method that returns an iterator.": {
|
||||
"category": "Error",
|
||||
"code": 2549
|
||||
},
|
||||
"Generic type instantiation is excessively deep and possibly infinite.": {
|
||||
"category": "Error",
|
||||
"code": 2550
|
||||
},
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
@@ -1795,7 +1843,7 @@
|
||||
"category": "Error",
|
||||
"code": 2602
|
||||
},
|
||||
"Property '{0}' in type '{1}' is not assignable to type '{2}'": {
|
||||
"Property '{0}' in type '{1}' is not assignable to type '{2}'.": {
|
||||
"category": "Error",
|
||||
"code": 2603
|
||||
},
|
||||
@@ -1811,11 +1859,11 @@
|
||||
"category": "Error",
|
||||
"code": 2606
|
||||
},
|
||||
"JSX element class does not support attributes because it does not have a '{0}' property": {
|
||||
"JSX element class does not support attributes because it does not have a '{0}' property.": {
|
||||
"category": "Error",
|
||||
"code": 2607
|
||||
},
|
||||
"The global type 'JSX.{0}' may not have more than one property": {
|
||||
"The global type 'JSX.{0}' may not have more than one property.": {
|
||||
"category": "Error",
|
||||
"code": 2608
|
||||
},
|
||||
@@ -1823,7 +1871,11 @@
|
||||
"category": "Error",
|
||||
"code": 2609
|
||||
},
|
||||
"Cannot emit namespaced JSX elements in React": {
|
||||
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
|
||||
"category": "Error",
|
||||
"code": 2649
|
||||
},
|
||||
"Cannot emit namespaced JSX elements in React.": {
|
||||
"category": "Error",
|
||||
"code": 2650
|
||||
},
|
||||
@@ -1847,11 +1899,11 @@
|
||||
"category": "Error",
|
||||
"code": 2656
|
||||
},
|
||||
"JSX expressions must have one parent element": {
|
||||
"JSX expressions must have one parent element.": {
|
||||
"category": "Error",
|
||||
"code": 2657
|
||||
},
|
||||
"Type '{0}' provides no match for the signature '{1}'": {
|
||||
"Type '{0}' provides no match for the signature '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2658
|
||||
},
|
||||
@@ -1979,10 +2031,6 @@
|
||||
"category": "Error",
|
||||
"code": 2689
|
||||
},
|
||||
"A class must be declared after its base class.": {
|
||||
"category": "Error",
|
||||
"code": 2690
|
||||
},
|
||||
"An import path cannot end with a '{0}' extension. Consider importing '{1}' instead.": {
|
||||
"category": "Error",
|
||||
"code": 2691
|
||||
@@ -2015,6 +2063,10 @@
|
||||
"category": "Error",
|
||||
"code": 2698
|
||||
},
|
||||
"Static property '{0}' conflicts with built-in property 'Function.{0}' of constructor function '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2699
|
||||
},
|
||||
"Rest types may only be created from object types.": {
|
||||
"category": "Error",
|
||||
"code": 2700
|
||||
@@ -2027,14 +2079,34 @@
|
||||
"category": "Error",
|
||||
"code": 2702
|
||||
},
|
||||
"The operand of a delete operator must be a property reference": {
|
||||
"The operand of a delete operator must be a property reference.": {
|
||||
"category": "Error",
|
||||
"code": 2703
|
||||
},
|
||||
"The operand of a delete operator cannot be a read-only property": {
|
||||
"The operand of a delete operator cannot be a read-only property.": {
|
||||
"category": "Error",
|
||||
"code": 2704
|
||||
},
|
||||
"An async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option.": {
|
||||
"category": "Error",
|
||||
"code": 2705
|
||||
},
|
||||
"Required type parameters may not follow optional type parameters.": {
|
||||
"category": "Error",
|
||||
"code": 2706
|
||||
},
|
||||
"Generic type '{0}' requires between {1} and {2} type arguments.": {
|
||||
"category": "Error",
|
||||
"code": 2707
|
||||
},
|
||||
"Cannot use namespace '{0}' as a value.": {
|
||||
"category": "Error",
|
||||
"code": 2708
|
||||
},
|
||||
"Cannot use namespace '{0}' as a type.": {
|
||||
"category": "Error",
|
||||
"code": 2709
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
@@ -2076,11 +2148,11 @@
|
||||
"category": "Error",
|
||||
"code": 4019
|
||||
},
|
||||
"Extends clause of exported class '{0}' has or is using private name '{1}'.": {
|
||||
"'extends' clause of exported class '{0}' has or is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4020
|
||||
},
|
||||
"Extends clause of exported interface '{0}' has or is using private name '{1}'.": {
|
||||
"'extends' clause of exported interface '{0}' has or is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 4022
|
||||
},
|
||||
@@ -2332,6 +2404,10 @@
|
||||
"category": "Error",
|
||||
"code": 4092
|
||||
},
|
||||
"'extends' clause of exported class '{0}' refers to a type whose name cannot be referenced.": {
|
||||
"category": "Error",
|
||||
"code": 4093
|
||||
},
|
||||
|
||||
"The current host does not support the '{0}' option.": {
|
||||
"category": "Error",
|
||||
@@ -2349,14 +2425,10 @@
|
||||
"category": "Error",
|
||||
"code": 5011
|
||||
},
|
||||
"Cannot read file '{0}': {1}": {
|
||||
"Cannot read file '{0}': {1}.": {
|
||||
"category": "Error",
|
||||
"code": 5012
|
||||
},
|
||||
"Unsupported file encoding.": {
|
||||
"category": "Error",
|
||||
"code": 5013
|
||||
},
|
||||
"Failed to parse file '{0}': {1}.": {
|
||||
"category": "Error",
|
||||
"code": 5014
|
||||
@@ -2369,7 +2441,7 @@
|
||||
"category": "Error",
|
||||
"code": 5024
|
||||
},
|
||||
"Could not write file '{0}': {1}": {
|
||||
"Could not write file '{0}': {1}.": {
|
||||
"category": "Error",
|
||||
"code": 5033
|
||||
},
|
||||
@@ -2405,11 +2477,11 @@
|
||||
"category": "Error",
|
||||
"code": 5056
|
||||
},
|
||||
"Cannot find a tsconfig.json file at the specified directory: '{0}'": {
|
||||
"Cannot find a tsconfig.json file at the specified directory: '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 5057
|
||||
},
|
||||
"The specified path does not exist: '{0}'": {
|
||||
"The specified path does not exist: '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 5058
|
||||
},
|
||||
@@ -2421,11 +2493,11 @@
|
||||
"category": "Error",
|
||||
"code": 5060
|
||||
},
|
||||
"Pattern '{0}' can have at most one '*' character": {
|
||||
"Pattern '{0}' can have at most one '*' character.": {
|
||||
"category": "Error",
|
||||
"code": 5061
|
||||
},
|
||||
"Substitution '{0}' in pattern '{1}' in can have at most one '*' character": {
|
||||
"Substitution '{0}' in pattern '{1}' in can have at most one '*' character.": {
|
||||
"category": "Error",
|
||||
"code": 5062
|
||||
},
|
||||
@@ -2497,11 +2569,11 @@
|
||||
"category": "Message",
|
||||
"code": 6012
|
||||
},
|
||||
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'": {
|
||||
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'.": {
|
||||
"category": "Message",
|
||||
"code": 6015
|
||||
},
|
||||
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'": {
|
||||
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'.": {
|
||||
"category": "Message",
|
||||
"code": 6016
|
||||
},
|
||||
@@ -2513,7 +2585,7 @@
|
||||
"category": "Message",
|
||||
"code": 6019
|
||||
},
|
||||
"Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'": {
|
||||
"Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.": {
|
||||
"category": "Message",
|
||||
"code": 6020
|
||||
},
|
||||
@@ -2593,7 +2665,7 @@
|
||||
"category": "Error",
|
||||
"code": 6045
|
||||
},
|
||||
"Argument for '{0}' option must be: {1}": {
|
||||
"Argument for '{0}' option must be: {1}.": {
|
||||
"category": "Error",
|
||||
"code": 6046
|
||||
},
|
||||
@@ -2681,7 +2753,7 @@
|
||||
"category": "Message",
|
||||
"code": 6072
|
||||
},
|
||||
"Stylize errors and messages using color and context. (experimental)": {
|
||||
"Stylize errors and messages using color and context (experimental).": {
|
||||
"category": "Message",
|
||||
"code": 6073
|
||||
},
|
||||
@@ -2709,7 +2781,7 @@
|
||||
"category": "Message",
|
||||
"code": 6079
|
||||
},
|
||||
"Specify JSX code generation: 'preserve' or 'react'": {
|
||||
"Specify JSX code generation: 'preserve', 'react-native', or 'react'.": {
|
||||
"category": "Message",
|
||||
"code": 6080
|
||||
},
|
||||
@@ -2725,7 +2797,7 @@
|
||||
"category": "Message",
|
||||
"code": 6083
|
||||
},
|
||||
"Specify the object invoked for createElement and __spread when targeting 'react' JSX emit": {
|
||||
"[Deprecated] Use '--jsxFactory' instead. Specify the object invoked for createElement when targeting 'react' JSX emit": {
|
||||
"category": "Message",
|
||||
"code": 6084
|
||||
},
|
||||
@@ -2789,7 +2861,7 @@
|
||||
"category": "Message",
|
||||
"code": 6099
|
||||
},
|
||||
"'package.json' does not have a 'types' or 'main' field.": {
|
||||
"'package.json' does not have a '{0}' field.": {
|
||||
"category": "Message",
|
||||
"code": 6100
|
||||
},
|
||||
@@ -2813,27 +2885,27 @@
|
||||
"category": "Message",
|
||||
"code": 6105
|
||||
},
|
||||
"'baseUrl' option is set to '{0}', using this value to resolve non-relative module name '{1}'": {
|
||||
"'baseUrl' option is set to '{0}', using this value to resolve non-relative module name '{1}'.": {
|
||||
"category": "Message",
|
||||
"code": 6106
|
||||
},
|
||||
"'rootDirs' option is set, using it to resolve relative module name '{0}'": {
|
||||
"'rootDirs' option is set, using it to resolve relative module name '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 6107
|
||||
},
|
||||
"Longest matching prefix for '{0}' is '{1}'": {
|
||||
"Longest matching prefix for '{0}' is '{1}'.": {
|
||||
"category": "Message",
|
||||
"code": 6108
|
||||
},
|
||||
"Loading '{0}' from the root dir '{1}', candidate location '{2}'": {
|
||||
"Loading '{0}' from the root dir '{1}', candidate location '{2}'.": {
|
||||
"category": "Message",
|
||||
"code": 6109
|
||||
},
|
||||
"Trying other entries in 'rootDirs'": {
|
||||
"Trying other entries in 'rootDirs'.": {
|
||||
"category": "Message",
|
||||
"code": 6110
|
||||
},
|
||||
"Module resolution using 'rootDirs' has failed": {
|
||||
"Module resolution using 'rootDirs' has failed.": {
|
||||
"category": "Message",
|
||||
"code": 6111
|
||||
},
|
||||
@@ -2873,7 +2945,7 @@
|
||||
"category": "Message",
|
||||
"code": 6120
|
||||
},
|
||||
"Resolving with primary search path '{0}'": {
|
||||
"Resolving with primary search path '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 6121
|
||||
},
|
||||
@@ -2889,7 +2961,7 @@
|
||||
"category": "Message",
|
||||
"code": 6124
|
||||
},
|
||||
"Looking up in 'node_modules' folder, initial location '{0}'": {
|
||||
"Looking up in 'node_modules' folder, initial location '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 6125
|
||||
},
|
||||
@@ -2909,7 +2981,7 @@
|
||||
"category": "Error",
|
||||
"code": 6129
|
||||
},
|
||||
"Resolving real path for '{0}', result '{1}'": {
|
||||
"Resolving real path for '{0}', result '{1}'.": {
|
||||
"category": "Message",
|
||||
"code": 6130
|
||||
},
|
||||
@@ -2917,7 +2989,7 @@
|
||||
"category": "Error",
|
||||
"code": 6131
|
||||
},
|
||||
"File name '{0}' has a '{1}' extension - stripping it": {
|
||||
"File name '{0}' has a '{1}' extension - stripping it.": {
|
||||
"category": "Message",
|
||||
"code": 6132
|
||||
},
|
||||
@@ -2933,14 +3005,10 @@
|
||||
"category": "Message",
|
||||
"code": 6135
|
||||
},
|
||||
"The maximum dependency depth to search under node_modules and load JavaScript files": {
|
||||
"The maximum dependency depth to search under node_modules and load JavaScript files.": {
|
||||
"category": "Message",
|
||||
"code": 6136
|
||||
},
|
||||
"No types specified in 'package.json', so returning 'main' value of '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 6137
|
||||
},
|
||||
"Property '{0}' is declared but never used.": {
|
||||
"category": "Error",
|
||||
"code": 6138
|
||||
@@ -2953,7 +3021,7 @@
|
||||
"category": "Error",
|
||||
"code": 6140
|
||||
},
|
||||
"Parse in strict mode and emit \"use strict\" for each source file": {
|
||||
"Parse in strict mode and emit \"use strict\" for each source file.": {
|
||||
"category": "Message",
|
||||
"code": 6141
|
||||
},
|
||||
@@ -2985,6 +3053,139 @@
|
||||
"category": "Message",
|
||||
"code": 6148
|
||||
},
|
||||
"Show diagnostic information.": {
|
||||
"category": "Message",
|
||||
"code": 6149
|
||||
},
|
||||
"Show verbose diagnostic information.": {
|
||||
"category": "Message",
|
||||
"code": 6150
|
||||
},
|
||||
"Emit a single file with source maps instead of having a separate file.": {
|
||||
"category": "Message",
|
||||
"code": 6151
|
||||
},
|
||||
"Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set.": {
|
||||
"category": "Message",
|
||||
"code": 6152
|
||||
},
|
||||
"Transpile each file as a separate module (similar to 'ts.transpileModule').": {
|
||||
"category": "Message",
|
||||
"code": 6153
|
||||
},
|
||||
"Print names of generated files part of the compilation.": {
|
||||
"category": "Message",
|
||||
"code": 6154
|
||||
},
|
||||
"Print names of files part of the compilation.": {
|
||||
"category": "Message",
|
||||
"code": 6155
|
||||
},
|
||||
"The locale used when displaying messages to the user (e.g. 'en-us')": {
|
||||
"category": "Message",
|
||||
"code": 6156
|
||||
},
|
||||
"Do not generate custom helper functions like '__extends' in compiled output.": {
|
||||
"category": "Message",
|
||||
"code": 6157
|
||||
},
|
||||
"Do not include the default library file (lib.d.ts).": {
|
||||
"category": "Message",
|
||||
"code": 6158
|
||||
},
|
||||
"Do not add triple-slash references or imported modules to the list of compiled files.": {
|
||||
"category": "Message",
|
||||
"code": 6159
|
||||
},
|
||||
"[Deprecated] Use '--skipLibCheck' instead. Skip type checking of default library declaration files.": {
|
||||
"category": "Message",
|
||||
"code": 6160
|
||||
},
|
||||
"List of folders to include type definitions from.": {
|
||||
"category": "Message",
|
||||
"code": 6161
|
||||
},
|
||||
"Disable size limitations on JavaScript projects.": {
|
||||
"category": "Message",
|
||||
"code": 6162
|
||||
},
|
||||
"The character set of the input files.": {
|
||||
"category": "Message",
|
||||
"code": 6163
|
||||
},
|
||||
"Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files.": {
|
||||
"category": "Message",
|
||||
"code": 6164
|
||||
},
|
||||
"Do not truncate error messages.": {
|
||||
"category": "Message",
|
||||
"code": 6165
|
||||
},
|
||||
"Output directory for generated declaration files.": {
|
||||
"category": "Message",
|
||||
"code": 6166
|
||||
},
|
||||
"A series of entries which re-map imports to lookup locations relative to the 'baseUrl'.": {
|
||||
"category": "Message",
|
||||
"code": 6167
|
||||
},
|
||||
"List of root folders whose combined content represents the structure of the project at runtime.": {
|
||||
"category": "Message",
|
||||
"code": 6168
|
||||
},
|
||||
"Show all compiler options.": {
|
||||
"category": "Message",
|
||||
"code": 6169
|
||||
},
|
||||
"[Deprecated] Use '--outFile' instead. Concatenate and emit output to single file": {
|
||||
"category": "Message",
|
||||
"code": 6170
|
||||
},
|
||||
"Command-line Options": {
|
||||
"category": "Message",
|
||||
"code": 6171
|
||||
},
|
||||
"Basic Options": {
|
||||
"category": "Message",
|
||||
"code": 6172
|
||||
},
|
||||
"Strict Type-Checking Options": {
|
||||
"category": "Message",
|
||||
"code": 6173
|
||||
},
|
||||
"Module Resolution Options": {
|
||||
"category": "Message",
|
||||
"code": 6174
|
||||
},
|
||||
"Source Map Options": {
|
||||
"category": "Message",
|
||||
"code": 6175
|
||||
},
|
||||
"Additional Checks": {
|
||||
"category": "Message",
|
||||
"code": 6176
|
||||
},
|
||||
"Experimental Options": {
|
||||
"category": "Message",
|
||||
"code": 6177
|
||||
},
|
||||
"Advanced Options": {
|
||||
"category": "Message",
|
||||
"code": 6178
|
||||
},
|
||||
"Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'.": {
|
||||
"category": "Message",
|
||||
"code": 6179
|
||||
},
|
||||
"Enable all strict type-checking options.": {
|
||||
"category": "Message",
|
||||
"code": 6180
|
||||
},
|
||||
"List of language service plugins.": {
|
||||
"category": "Message",
|
||||
"code": 6181
|
||||
},
|
||||
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
"code": 7005
|
||||
@@ -3053,7 +3254,7 @@
|
||||
"category": "Error",
|
||||
"code": 7025
|
||||
},
|
||||
"JSX element implicitly has type 'any' because no interface 'JSX.{0}' exists": {
|
||||
"JSX element implicitly has type 'any' because no interface 'JSX.{0}' exists.": {
|
||||
"category": "Error",
|
||||
"code": 7026
|
||||
},
|
||||
@@ -3149,7 +3350,7 @@
|
||||
"category": "Error",
|
||||
"code": 8016
|
||||
},
|
||||
"Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses.": {
|
||||
"Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": {
|
||||
"category": "Error",
|
||||
"code": 9002
|
||||
},
|
||||
@@ -3181,7 +3382,7 @@
|
||||
"category": "Error",
|
||||
"code": 17004
|
||||
},
|
||||
"A constructor cannot contain a 'super' call when its class extends 'null'": {
|
||||
"A constructor cannot contain a 'super' call when its class extends 'null'.": {
|
||||
"category": "Error",
|
||||
"code": 17005
|
||||
},
|
||||
@@ -3209,7 +3410,7 @@
|
||||
"category": "Error",
|
||||
"code": 17011
|
||||
},
|
||||
"'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{0}'?": {
|
||||
"'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{2}'?": {
|
||||
"category": "Error",
|
||||
"code": 17012
|
||||
},
|
||||
@@ -3247,7 +3448,7 @@
|
||||
"category": "Message",
|
||||
"code": 90003
|
||||
},
|
||||
"Remove declaration for: {0}": {
|
||||
"Remove declaration for: '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90004
|
||||
},
|
||||
@@ -3259,7 +3460,11 @@
|
||||
"category": "Message",
|
||||
"code": 90007
|
||||
},
|
||||
"Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig": {
|
||||
"Add 'this.' to unresolved variable.": {
|
||||
"category": "Message",
|
||||
"code": 90008
|
||||
},
|
||||
"Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.": {
|
||||
"category": "Error",
|
||||
"code": 90009
|
||||
},
|
||||
@@ -3267,18 +3472,44 @@
|
||||
"category": "Error",
|
||||
"code": 90010
|
||||
},
|
||||
"Import {0} from {1}": {
|
||||
"Import {0} from {1}.": {
|
||||
"category": "Message",
|
||||
"code": 90013
|
||||
},
|
||||
"Change {0} to {1}": {
|
||||
"Change {0} to {1}.": {
|
||||
"category": "Message",
|
||||
"code": 90014
|
||||
},
|
||||
"Add {0} to existing import declaration from {1}": {
|
||||
"Add {0} to existing import declaration from {1}.": {
|
||||
"category": "Message",
|
||||
"code": 90015
|
||||
},
|
||||
"Add declaration for missing property '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90016
|
||||
},
|
||||
"Add index signature for missing property '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90017
|
||||
},
|
||||
"Disable checking for this file.": {
|
||||
"category": "Message",
|
||||
"code": 90018
|
||||
},
|
||||
"Ignore this error message.": {
|
||||
"category": "Message",
|
||||
"code": 90019
|
||||
},
|
||||
"Initialize property '{0}' in the constructor.": {
|
||||
"category": "Message",
|
||||
"code": 90020
|
||||
},
|
||||
"Initialize static property '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90021
|
||||
},
|
||||
|
||||
|
||||
"Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 8017
|
||||
@@ -3286,5 +3517,9 @@
|
||||
"Octal literals are not allowed in enums members initializer. Use the syntax '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 8018
|
||||
},
|
||||
"Report errors in .js files.": {
|
||||
"category": "Message",
|
||||
"code": 8019
|
||||
}
|
||||
}
|
||||
|
||||
+650
-481
File diff suppressed because it is too large
Load Diff
+1831
-1135
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/// <reference path="core.ts" />
|
||||
/// <reference path="core.ts" />
|
||||
/// <reference path="diagnosticInformationMap.generated.ts" />
|
||||
|
||||
namespace ts {
|
||||
@@ -67,40 +67,31 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** Reads from "main" or "types"/"typings" depending on `extensions`. */
|
||||
function tryReadPackageJsonMainOrTypes(extensions: Extensions, packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string {
|
||||
function tryReadPackageJsonFields(readTypes: boolean, packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string | undefined {
|
||||
const jsonContent = readJson(packageJsonPath, state.host);
|
||||
return readTypes ? tryReadFromField("typings") || tryReadFromField("types") : tryReadFromField("main");
|
||||
|
||||
switch (extensions) {
|
||||
case Extensions.DtsOnly:
|
||||
case Extensions.TypeScript:
|
||||
return tryReadFromField("typings") || tryReadFromField("types");
|
||||
|
||||
case Extensions.JavaScript:
|
||||
if (typeof jsonContent.main === "string") {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.No_types_specified_in_package_json_so_returning_main_value_of_0, jsonContent.main);
|
||||
}
|
||||
return normalizePath(combinePaths(baseDirectory, jsonContent.main));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function tryReadFromField(fieldName: string) {
|
||||
if (hasProperty(jsonContent, fieldName)) {
|
||||
const typesFile = (<any>jsonContent)[fieldName];
|
||||
if (typeof typesFile === "string") {
|
||||
const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile));
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath);
|
||||
}
|
||||
return typesFilePath;
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile);
|
||||
}
|
||||
function tryReadFromField(fieldName: "typings" | "types" | "main"): string | undefined {
|
||||
if (!hasProperty(jsonContent, fieldName)) {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_does_not_have_a_0_field, fieldName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const fileName = jsonContent[fieldName];
|
||||
if (typeof fileName !== "string") {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof fileName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const path = normalizePath(combinePaths(baseDirectory, fileName));
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, fileName, path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +135,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
let typeRoots: string[];
|
||||
forEachAncestorDirectory(currentDirectory, directory => {
|
||||
forEachAncestorDirectory(ts.normalizePath(currentDirectory), directory => {
|
||||
const atTypes = combinePaths(directory, nodeModulesAtTypes);
|
||||
if (host.directoryExists(atTypes)) {
|
||||
(typeRoots || (typeRoots = [])).push(atTypes);
|
||||
@@ -258,13 +249,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a set of options, returns the set of type directive names
|
||||
* that should be included for this program automatically.
|
||||
* This list could either come from the config file,
|
||||
* or from enumerating the types root + initial secondary types lookup location.
|
||||
* More type directives might appear in the program later as a result of loading actual source files;
|
||||
* this list is only the set of defaults that are implicitly included.
|
||||
*/
|
||||
* Given a set of options, returns the set of type directive names
|
||||
* that should be included for this program automatically.
|
||||
* This list could either come from the config file,
|
||||
* or from enumerating the types root + initial secondary types lookup location.
|
||||
* More type directives might appear in the program later as a result of loading actual source files;
|
||||
* this list is only the set of defaults that are implicitly included.
|
||||
*/
|
||||
export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[] {
|
||||
// Use explicit type list from tsconfig.json
|
||||
if (options.types) {
|
||||
@@ -665,7 +656,7 @@ namespace ts {
|
||||
// A path mapping may have a ".ts" extension; in contrast to an import, which should omit it.
|
||||
const tsExtension = tryGetExtensionFromPath(candidate);
|
||||
if (tsExtension !== undefined) {
|
||||
const path = tryFile(candidate, failedLookupLocations, /*onlyRecordFailures*/false, state);
|
||||
const path = tryFile(candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
return path && { path, extension: tsExtension };
|
||||
}
|
||||
|
||||
@@ -684,13 +675,18 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations {
|
||||
return nodeModuleNameResolverWorker(moduleName, containingFile, compilerOptions, host, cache, /*jsOnly*/ false);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function nodeModuleNameResolverWorker(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, jsOnly = false): ResolvedModuleWithFailedLookupLocations {
|
||||
const containingDirectory = getDirectoryPath(containingFile);
|
||||
const traceEnabled = isTraceEnabled(compilerOptions, host);
|
||||
|
||||
const failedLookupLocations: string[] = [];
|
||||
const state: ModuleResolutionState = { compilerOptions, host, traceEnabled };
|
||||
|
||||
const result = tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript);
|
||||
const result = jsOnly ? tryResolve(Extensions.JavaScript) : (tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript));
|
||||
if (result && result.value) {
|
||||
const { resolved, isExternalLibraryImport } = result.value;
|
||||
return createResolvedModuleWithFailedLookupLocations(resolved, isExternalLibraryImport, failedLookupLocations);
|
||||
@@ -698,7 +694,8 @@ namespace ts {
|
||||
return { resolvedModule: undefined, failedLookupLocations };
|
||||
|
||||
function tryResolve(extensions: Extensions): SearchResult<{ resolved: Resolved, isExternalLibraryImport: boolean }> {
|
||||
const resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, nodeLoadModuleByRelativeName, failedLookupLocations, state);
|
||||
const loader: ResolutionKindSpecificLoader = (extensions, candidate, failedLookupLocations, onlyRecordFailures, state) => nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ true);
|
||||
const resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state);
|
||||
if (resolved) {
|
||||
return toSearchResult({ resolved, isExternalLibraryImport: false });
|
||||
}
|
||||
@@ -713,7 +710,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
const resolved = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
const resolved = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true);
|
||||
return resolved && toSearchResult({ resolved, isExternalLibraryImport: false });
|
||||
}
|
||||
}
|
||||
@@ -731,7 +728,7 @@ namespace ts {
|
||||
return real;
|
||||
}
|
||||
|
||||
function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson: boolean): Resolved | undefined {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0_target_file_type_1, candidate, Extensions[extensions]);
|
||||
}
|
||||
@@ -759,7 +756,7 @@ namespace ts {
|
||||
onlyRecordFailures = true;
|
||||
}
|
||||
}
|
||||
return loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, onlyRecordFailures, state);
|
||||
return loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, considerPackageJson);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -835,50 +832,57 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined {
|
||||
const packageJsonPath = pathToPackageJson(candidate);
|
||||
function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson = true): Resolved | undefined {
|
||||
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
|
||||
|
||||
if (directoryExists && state.host.fileExists(packageJsonPath)) {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Found_package_json_at_0, packageJsonPath);
|
||||
}
|
||||
const mainOrTypesFile = tryReadPackageJsonMainOrTypes(extensions, packageJsonPath, candidate, state);
|
||||
if (mainOrTypesFile) {
|
||||
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(mainOrTypesFile), state.host);
|
||||
// A package.json "typings" may specify an exact filename, or may choose to omit an extension.
|
||||
const fromExactFile = tryFile(mainOrTypesFile, failedLookupLocations, onlyRecordFailures, state);
|
||||
if (fromExactFile) {
|
||||
const resolved = fromExactFile && resolvedIfExtensionMatches(extensions, fromExactFile);
|
||||
if (resolved) {
|
||||
return resolved;
|
||||
}
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_has_an_unsupported_extension_so_skipping_it, fromExactFile);
|
||||
}
|
||||
}
|
||||
const resolved = tryAddingExtensions(mainOrTypesFile, Extensions.TypeScript, failedLookupLocations, onlyRecordFailures, state);
|
||||
if (resolved) {
|
||||
return resolved;
|
||||
if (considerPackageJson) {
|
||||
const packageJsonPath = pathToPackageJson(candidate);
|
||||
if (directoryExists && state.host.fileExists(packageJsonPath)) {
|
||||
const fromPackageJson = loadModuleFromPackageJson(packageJsonPath, extensions, candidate, failedLookupLocations, state);
|
||||
if (fromPackageJson) {
|
||||
return fromPackageJson;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.package_json_does_not_have_a_types_or_main_field);
|
||||
if (directoryExists && state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_does_not_exist, packageJsonPath);
|
||||
}
|
||||
// record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results
|
||||
failedLookupLocations.push(packageJsonPath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (directoryExists && state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_does_not_exist, packageJsonPath);
|
||||
}
|
||||
// record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results
|
||||
failedLookupLocations.push(packageJsonPath);
|
||||
}
|
||||
|
||||
return loadModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocations, !directoryExists, state);
|
||||
}
|
||||
|
||||
function loadModuleFromPackageJson(packageJsonPath: string, extensions: Extensions, candidate: string, failedLookupLocations: Push<string>, state: ModuleResolutionState): Resolved | undefined {
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.Found_package_json_at_0, packageJsonPath);
|
||||
}
|
||||
|
||||
const file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript, packageJsonPath, candidate, state);
|
||||
if (!file) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(file), state.host);
|
||||
const fromFile = tryFile(file, failedLookupLocations, onlyRecordFailures, state);
|
||||
if (fromFile) {
|
||||
const resolved = fromFile && resolvedIfExtensionMatches(extensions, fromFile);
|
||||
if (resolved) {
|
||||
return resolved;
|
||||
}
|
||||
if (state.traceEnabled) {
|
||||
trace(state.host, Diagnostics.File_0_has_an_unsupported_extension_so_skipping_it, fromFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Even if extensions is DtsOnly, we can still look up a .ts file as a result of package.json "types"
|
||||
const nextExtensions = extensions === Extensions.DtsOnly ? Extensions.TypeScript : extensions;
|
||||
// Don't do package.json lookup recursively, because Node.js' package lookup doesn't.
|
||||
return nodeLoadModuleByRelativeName(nextExtensions, file, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ false);
|
||||
}
|
||||
|
||||
/** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */
|
||||
function resolvedIfExtensionMatches(extensions: Extensions, path: string): Resolved | undefined {
|
||||
const extension = tryGetExtensionFromPath(path);
|
||||
@@ -958,7 +962,7 @@ namespace ts {
|
||||
const result = cache && cache.get(containingDirectory);
|
||||
if (result) {
|
||||
if (traceEnabled) {
|
||||
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache, moduleName)
|
||||
trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache, moduleName);
|
||||
}
|
||||
return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, extension: result.resolvedModule.extension } };
|
||||
}
|
||||
@@ -1040,7 +1044,6 @@ namespace ts {
|
||||
return value !== undefined ? { value } : undefined;
|
||||
}
|
||||
|
||||
|
||||
/** Calls `callback` on `directory` and every ancestor directory it has, returning the first defined result. */
|
||||
function forEachAncestorDirectory<T>(directory: string, callback: (directory: string) => SearchResult<T>): SearchResult<T> {
|
||||
while (true) {
|
||||
@@ -1057,4 +1060,4 @@ namespace ts {
|
||||
directory = parentPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+102
-58
@@ -66,6 +66,7 @@ namespace ts {
|
||||
case SyntaxKind.TypeParameter:
|
||||
return visitNode(cbNode, (<TypeParameterDeclaration>node).name) ||
|
||||
visitNode(cbNode, (<TypeParameterDeclaration>node).constraint) ||
|
||||
visitNode(cbNode, (<TypeParameterDeclaration>node).default) ||
|
||||
visitNode(cbNode, (<TypeParameterDeclaration>node).expression);
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
return visitNodes(cbNodes, node.decorators) ||
|
||||
@@ -242,7 +243,8 @@ namespace ts {
|
||||
visitNode(cbNode, (<ForInStatement>node).expression) ||
|
||||
visitNode(cbNode, (<ForInStatement>node).statement);
|
||||
case SyntaxKind.ForOfStatement:
|
||||
return visitNode(cbNode, (<ForOfStatement>node).initializer) ||
|
||||
return visitNode(cbNode, (<ForOfStatement>node).awaitModifier) ||
|
||||
visitNode(cbNode, (<ForOfStatement>node).initializer) ||
|
||||
visitNode(cbNode, (<ForOfStatement>node).expression) ||
|
||||
visitNode(cbNode, (<ForOfStatement>node).statement);
|
||||
case SyntaxKind.ContinueStatement:
|
||||
@@ -368,7 +370,9 @@ namespace ts {
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
return visitNode(cbNode, (<JsxOpeningLikeElement>node).tagName) ||
|
||||
visitNodes(cbNodes, (<JsxOpeningLikeElement>node).attributes);
|
||||
visitNode(cbNode, (<JsxOpeningLikeElement>node).attributes);
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return visitNodes(cbNodes, (<JsxAttributes>node).properties);
|
||||
case SyntaxKind.JsxAttribute:
|
||||
return visitNode(cbNode, (<JsxAttribute>node).name) ||
|
||||
visitNode(cbNode, (<JsxAttribute>node).initializer);
|
||||
@@ -454,6 +458,7 @@ namespace ts {
|
||||
return Parser.parseIsolatedEntityName(text, languageVersion);
|
||||
}
|
||||
|
||||
// See also `isExternalOrCommonJsModule` in utilities.ts
|
||||
export function isExternalModule(file: SourceFile): boolean {
|
||||
return file.externalModuleIndicator !== undefined;
|
||||
}
|
||||
@@ -1263,6 +1268,7 @@ namespace ts {
|
||||
function nextTokenIsClassOrFunctionOrAsync(): boolean {
|
||||
nextToken();
|
||||
return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword ||
|
||||
(token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) ||
|
||||
(token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine));
|
||||
}
|
||||
|
||||
@@ -1305,7 +1311,7 @@ namespace ts {
|
||||
case ParsingContext.ObjectBindingElements:
|
||||
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
|
||||
case ParsingContext.HeritageClauseElement:
|
||||
// If we see { } then only consume it as an expression if it is followed by , or {
|
||||
// If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{`
|
||||
// That way we won't consume the body of a class in its heritage clause.
|
||||
if (token() === SyntaxKind.OpenBraceToken) {
|
||||
return lookAhead(isValidHeritageClauseObjectLiteral);
|
||||
@@ -1840,7 +1846,7 @@ namespace ts {
|
||||
case ParsingContext.JSDocTupleTypes: return Diagnostics.Type_expected;
|
||||
case ParsingContext.JSDocRecordMembers: return Diagnostics.Property_assignment_expected;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Parses a comma-delimited list of elements
|
||||
function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<T> {
|
||||
@@ -2026,32 +2032,27 @@ namespace ts {
|
||||
node.isUnterminated = true;
|
||||
}
|
||||
|
||||
const tokenPos = scanner.getTokenPos();
|
||||
nextToken();
|
||||
finishNode(node);
|
||||
|
||||
// Octal literals are not allowed in strict mode or ES5
|
||||
// Note that theoretically the following condition would hold true literals like 009,
|
||||
// which is not octal.But because of how the scanner separates the tokens, we would
|
||||
// never get a token like this. Instead, we would get 00 and 9 as two separate tokens.
|
||||
// We also do not need to check for negatives because any prefix operator would be part of a
|
||||
// parent unary expression.
|
||||
if (node.kind === SyntaxKind.NumericLiteral
|
||||
&& sourceText.charCodeAt(tokenPos) === CharacterCodes._0
|
||||
&& isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) {
|
||||
|
||||
node.isOctalLiteral = true;
|
||||
if (node.kind === SyntaxKind.NumericLiteral) {
|
||||
(<NumericLiteral>node).numericLiteralFlags = scanner.getNumericLiteralFlags();
|
||||
}
|
||||
|
||||
nextToken();
|
||||
finishNode(node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// TYPES
|
||||
|
||||
function parseTypeReference(): TypeReferenceNode {
|
||||
const typeName = parseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected);
|
||||
const node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference, typeName.pos);
|
||||
node.typeName = typeName;
|
||||
const node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
|
||||
node.typeName = parseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected);
|
||||
if (!scanner.hasPrecedingLineBreak() && token() === SyntaxKind.LessThanToken) {
|
||||
node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
@@ -2102,10 +2103,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (parseOptional(SyntaxKind.EqualsToken)) {
|
||||
node.default = parseType();
|
||||
}
|
||||
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseTypeParameters(): NodeArray<TypeParameterDeclaration> {
|
||||
function parseTypeParameters(): NodeArray<TypeParameterDeclaration> | undefined {
|
||||
if (token() === SyntaxKind.LessThanToken) {
|
||||
return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
@@ -2126,7 +2131,7 @@ namespace ts {
|
||||
function parseParameter(): ParameterDeclaration {
|
||||
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter);
|
||||
if (token() === SyntaxKind.ThisKeyword) {
|
||||
node.name = createIdentifier(/*isIdentifier*/true, undefined);
|
||||
node.name = createIdentifier(/*isIdentifier*/ true);
|
||||
node.type = parseParameterType();
|
||||
return finishNode(node);
|
||||
}
|
||||
@@ -2175,7 +2180,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function fillSignature(
|
||||
returnToken: SyntaxKind,
|
||||
returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken,
|
||||
yieldContext: boolean,
|
||||
awaitContext: boolean,
|
||||
requireCompleteParameterList: boolean,
|
||||
@@ -2365,14 +2370,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isTypeMemberStart(): boolean {
|
||||
let idToken: SyntaxKind;
|
||||
// Return true if we have the start of a signature member
|
||||
if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
|
||||
return true;
|
||||
}
|
||||
let idToken: boolean;
|
||||
// Eat up all modifiers, but hold on to the last one in case it is actually an identifier
|
||||
while (isModifierKind(token())) {
|
||||
idToken = token();
|
||||
idToken = true;
|
||||
nextToken();
|
||||
}
|
||||
// Index signatures and computed property names are type members
|
||||
@@ -2381,7 +2386,7 @@ namespace ts {
|
||||
}
|
||||
// Try to get the first property-like token following all modifiers
|
||||
if (isLiteralPropertyName()) {
|
||||
idToken = token();
|
||||
idToken = true;
|
||||
nextToken();
|
||||
}
|
||||
// If we were able to get any potential identifier, check that it is
|
||||
@@ -2489,7 +2494,7 @@ namespace ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseKeywordAndNoDot(): TypeNode {
|
||||
function parseKeywordAndNoDot(): TypeNode | undefined {
|
||||
const node = parseTokenNode<TypeNode>();
|
||||
return token() === SyntaxKind.DotToken ? undefined : node;
|
||||
}
|
||||
@@ -2627,7 +2632,7 @@ namespace ts {
|
||||
return parseArrayTypeOrHigher();
|
||||
}
|
||||
|
||||
function parseUnionOrIntersectionType(kind: SyntaxKind, parseConstituentType: () => TypeNode, operator: SyntaxKind): TypeNode {
|
||||
function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode {
|
||||
parseOptional(operator);
|
||||
let type = parseConstituentType();
|
||||
if (token() === operator) {
|
||||
@@ -3035,7 +3040,7 @@ namespace ts {
|
||||
// If we have an arrow, then try to parse the body. Even if not, try to parse if we
|
||||
// have an opening brace, just in case we're in an error state.
|
||||
const lastToken = token();
|
||||
arrowFunction.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/false, Diagnostics._0_expected, "=>");
|
||||
arrowFunction.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, "=>");
|
||||
arrowFunction.body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken)
|
||||
? parseArrowFunctionExpressionBody(isAsync)
|
||||
: parseIdentifier();
|
||||
@@ -3804,7 +3809,7 @@ namespace ts {
|
||||
// Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios
|
||||
// of one sort or another.
|
||||
if (inExpressionContext && token() === SyntaxKind.LessThanToken) {
|
||||
const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElement(/*inExpressionContext*/true));
|
||||
const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElement(/*inExpressionContext*/ true));
|
||||
if (invalidElement) {
|
||||
parseErrorAtCurrentToken(Diagnostics.JSX_expressions_must_have_one_parent_element);
|
||||
const badNode = <BinaryExpression>createNode(SyntaxKind.BinaryExpression, result.pos);
|
||||
@@ -3855,6 +3860,9 @@ namespace ts {
|
||||
parseErrorAtPosition(openingTagName.pos, openingTagName.end - openingTagName.pos, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTagName));
|
||||
break;
|
||||
}
|
||||
else if (token() === SyntaxKind.ConflictMarkerTrivia) {
|
||||
break;
|
||||
}
|
||||
result.push(parseJsxChild());
|
||||
}
|
||||
|
||||
@@ -3865,14 +3873,20 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseJsxAttributes(): JsxAttributes {
|
||||
const jsxAttributes = <JsxAttributes>createNode(SyntaxKind.JsxAttributes);
|
||||
jsxAttributes.properties = parseList(ParsingContext.JsxAttributes, parseJsxAttribute);
|
||||
return finishNode(jsxAttributes);
|
||||
}
|
||||
|
||||
function parseJsxOpeningOrSelfClosingElement(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement {
|
||||
const fullStart = scanner.getStartPos();
|
||||
|
||||
parseExpected(SyntaxKind.LessThanToken);
|
||||
|
||||
const tagName = parseJsxElementName();
|
||||
const attributes = parseJsxAttributes();
|
||||
|
||||
const attributes = parseList(ParsingContext.JsxAttributes, parseJsxAttribute);
|
||||
let node: JsxOpeningLikeElement;
|
||||
|
||||
if (token() === SyntaxKind.GreaterThanToken) {
|
||||
@@ -4448,6 +4462,7 @@ namespace ts {
|
||||
function parseForOrForInOrForOfStatement(): Statement {
|
||||
const pos = getNodePos();
|
||||
parseExpected(SyntaxKind.ForKeyword);
|
||||
const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword);
|
||||
parseExpected(SyntaxKind.OpenParenToken);
|
||||
|
||||
let initializer: VariableDeclarationList | Expression = undefined;
|
||||
@@ -4460,20 +4475,21 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
let forOrForInOrForOfStatement: IterationStatement;
|
||||
if (parseOptional(SyntaxKind.InKeyword)) {
|
||||
if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) {
|
||||
const forOfStatement = <ForOfStatement>createNode(SyntaxKind.ForOfStatement, pos);
|
||||
forOfStatement.awaitModifier = awaitToken;
|
||||
forOfStatement.initializer = initializer;
|
||||
forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
forOrForInOrForOfStatement = forOfStatement;
|
||||
}
|
||||
else if (parseOptional(SyntaxKind.InKeyword)) {
|
||||
const forInStatement = <ForInStatement>createNode(SyntaxKind.ForInStatement, pos);
|
||||
forInStatement.initializer = initializer;
|
||||
forInStatement.expression = allowInAnd(parseExpression);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
forOrForInOrForOfStatement = forInStatement;
|
||||
}
|
||||
else if (parseOptional(SyntaxKind.OfKeyword)) {
|
||||
const forOfStatement = <ForOfStatement>createNode(SyntaxKind.ForOfStatement, pos);
|
||||
forOfStatement.initializer = initializer;
|
||||
forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
forOrForInOrForOfStatement = forOfStatement;
|
||||
}
|
||||
else {
|
||||
const forStatement = <ForStatement>createNode(SyntaxKind.ForStatement, pos);
|
||||
forStatement.initializer = initializer;
|
||||
@@ -4642,6 +4658,11 @@ namespace ts {
|
||||
return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak();
|
||||
}
|
||||
|
||||
function nextTokenIsClassKeywordOnSameLine() {
|
||||
nextToken();
|
||||
return token() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak();
|
||||
}
|
||||
|
||||
function nextTokenIsFunctionKeywordOnSameLine() {
|
||||
nextToken();
|
||||
return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak();
|
||||
@@ -5265,8 +5286,8 @@ namespace ts {
|
||||
*
|
||||
* In such situations, 'permitInvalidConstAsModifier' should be set to true.
|
||||
*/
|
||||
function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray<Modifier> {
|
||||
let modifiers: NodeArray<Modifier>;
|
||||
function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray<Modifier> | undefined {
|
||||
let modifiers: NodeArray<Modifier> | undefined;
|
||||
while (true) {
|
||||
const modifierStart = scanner.getStartPos();
|
||||
const modifierKind = token();
|
||||
@@ -5406,7 +5427,7 @@ namespace ts {
|
||||
return token() === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword);
|
||||
}
|
||||
|
||||
function parseHeritageClauses(): NodeArray<HeritageClause> {
|
||||
function parseHeritageClauses(): NodeArray<HeritageClause> | undefined {
|
||||
// ClassTail[Yield,Await] : (Modified) See 14.5
|
||||
// ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
|
||||
|
||||
@@ -5417,10 +5438,11 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseHeritageClause() {
|
||||
if (token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword) {
|
||||
function parseHeritageClause(): HeritageClause | undefined {
|
||||
const tok = token();
|
||||
if (tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword) {
|
||||
const node = <HeritageClause>createNode(SyntaxKind.HeritageClause);
|
||||
node.token = token();
|
||||
node.token = tok;
|
||||
nextToken();
|
||||
node.types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments);
|
||||
return finishNode(node);
|
||||
@@ -5443,7 +5465,7 @@ namespace ts {
|
||||
return token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
|
||||
}
|
||||
|
||||
function parseClassMembers() {
|
||||
function parseClassMembers(): NodeArray<ClassElement> {
|
||||
return parseList(ParsingContext.ClassMembers, parseClassElement);
|
||||
}
|
||||
|
||||
@@ -5602,17 +5624,7 @@ namespace ts {
|
||||
if (isIdentifier()) {
|
||||
identifier = parseIdentifier();
|
||||
if (token() !== SyntaxKind.CommaToken && token() !== SyntaxKind.FromKeyword) {
|
||||
// ImportEquals declaration of type:
|
||||
// import x = require("mod"); or
|
||||
// import x = M.x;
|
||||
const importEqualsDeclaration = <ImportEqualsDeclaration>createNode(SyntaxKind.ImportEqualsDeclaration, fullStart);
|
||||
importEqualsDeclaration.decorators = decorators;
|
||||
importEqualsDeclaration.modifiers = modifiers;
|
||||
importEqualsDeclaration.name = identifier;
|
||||
parseExpected(SyntaxKind.EqualsToken);
|
||||
importEqualsDeclaration.moduleReference = parseModuleReference();
|
||||
parseSemicolon();
|
||||
return addJSDocComment(finishNode(importEqualsDeclaration));
|
||||
return parseImportEqualsDeclaration(fullStart, decorators, modifiers, identifier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5636,6 +5648,17 @@ namespace ts {
|
||||
return finishNode(importDeclaration);
|
||||
}
|
||||
|
||||
function parseImportEqualsDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>, identifier: ts.Identifier): ImportEqualsDeclaration {
|
||||
const importEqualsDeclaration = <ImportEqualsDeclaration>createNode(SyntaxKind.ImportEqualsDeclaration, fullStart);
|
||||
importEqualsDeclaration.decorators = decorators;
|
||||
importEqualsDeclaration.modifiers = modifiers;
|
||||
importEqualsDeclaration.name = identifier;
|
||||
parseExpected(SyntaxKind.EqualsToken);
|
||||
importEqualsDeclaration.moduleReference = parseModuleReference();
|
||||
parseSemicolon();
|
||||
return addJSDocComment(finishNode(importEqualsDeclaration));
|
||||
}
|
||||
|
||||
function parseImportClause(identifier: Identifier, fullStart: number) {
|
||||
// ImportClause:
|
||||
// ImportedDefaultBinding
|
||||
@@ -5796,11 +5819,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function processReferenceComments(sourceFile: SourceFile): void {
|
||||
const triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/false, LanguageVariant.Standard, sourceText);
|
||||
const triviaScanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, LanguageVariant.Standard, sourceText);
|
||||
const referencedFiles: FileReference[] = [];
|
||||
const typeReferenceDirectives: FileReference[] = [];
|
||||
const amdDependencies: { path: string; name: string }[] = [];
|
||||
let amdModuleName: string;
|
||||
let checkJsDirective: CheckJsDirective = undefined;
|
||||
|
||||
// Keep scanning all the leading trivia in the file until we get to something that
|
||||
// isn't trivia. Any single line comment will be analyzed to see if it is a
|
||||
@@ -5816,7 +5840,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const range = { pos: triviaScanner.getTokenPos(), end: triviaScanner.getTextPos(), kind: triviaScanner.getToken() };
|
||||
const range = {
|
||||
kind: <SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia>triviaScanner.getToken(),
|
||||
pos: triviaScanner.getTokenPos(),
|
||||
end: triviaScanner.getTextPos(),
|
||||
};
|
||||
|
||||
const comment = sourceText.substring(range.pos, range.end);
|
||||
const referencePathMatchResult = getFileReferenceFromReferencePath(comment, range);
|
||||
@@ -5858,6 +5886,16 @@ namespace ts {
|
||||
amdDependencies.push(amdDependency);
|
||||
}
|
||||
}
|
||||
|
||||
const checkJsDirectiveRegEx = /^\/\/\/?\s*(@ts-check|@ts-nocheck)\s*$/gim;
|
||||
const checkJsDirectiveMatchResult = checkJsDirectiveRegEx.exec(comment);
|
||||
if (checkJsDirectiveMatchResult) {
|
||||
checkJsDirective = {
|
||||
enabled: compareStrings(checkJsDirectiveMatchResult[1], "@ts-check", /*ignoreCase*/ true) === Comparison.EqualTo,
|
||||
end: range.end,
|
||||
pos: range.pos
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5865,6 +5903,7 @@ namespace ts {
|
||||
sourceFile.typeReferenceDirectives = typeReferenceDirectives;
|
||||
sourceFile.amdDependencies = amdDependencies;
|
||||
sourceFile.moduleName = amdModuleName;
|
||||
sourceFile.checkJsDirective = checkJsDirective;
|
||||
}
|
||||
|
||||
function setExternalModuleIndicator(sourceFile: SourceFile) {
|
||||
@@ -6491,7 +6530,7 @@ namespace ts {
|
||||
|
||||
function parseTagComments(indent: number) {
|
||||
const comments: string[] = [];
|
||||
let state = JSDocState.SawAsterisk;
|
||||
let state = JSDocState.BeginningOfLine;
|
||||
let margin: number | undefined;
|
||||
function pushComment(text: string) {
|
||||
if (!margin) {
|
||||
@@ -6693,10 +6732,15 @@ namespace ts {
|
||||
typedefTag.fullName = parseJSDocTypeNameWithNamespace(/*flags*/ 0);
|
||||
if (typedefTag.fullName) {
|
||||
let rightNode = typedefTag.fullName;
|
||||
while (rightNode.kind !== SyntaxKind.Identifier) {
|
||||
while (true) {
|
||||
if (rightNode.kind === SyntaxKind.Identifier || !rightNode.body) {
|
||||
// if node is identifier - use it as name
|
||||
// otherwise use name of the rightmost part that we were able to parse
|
||||
typedefTag.name = rightNode.kind === SyntaxKind.Identifier ? rightNode : rightNode.name;
|
||||
break;
|
||||
}
|
||||
rightNode = rightNode.body;
|
||||
}
|
||||
typedefTag.name = rightNode;
|
||||
}
|
||||
typedefTag.typeExpression = typeExpression;
|
||||
skipWhitespace();
|
||||
|
||||
+92
-26
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace ts {
|
||||
const emptyArray: any[] = [];
|
||||
const ignoreDiagnosticCommentRegEx = /(^\s*$)|(^\s*\/\/\/?\s*(@ts-ignore)?)/;
|
||||
|
||||
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName = "tsconfig.json"): string {
|
||||
while (true) {
|
||||
@@ -87,9 +88,6 @@ namespace ts {
|
||||
return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
||||
}
|
||||
|
||||
// returned by CScript sys environment
|
||||
const unsupportedFileEncodingErrorCode = -2147024809;
|
||||
|
||||
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
|
||||
let text: string;
|
||||
try {
|
||||
@@ -100,9 +98,7 @@ namespace ts {
|
||||
}
|
||||
catch (e) {
|
||||
if (onError) {
|
||||
onError(e.number === unsupportedFileEncodingErrorCode
|
||||
? createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText
|
||||
: e.message);
|
||||
onError(e.message);
|
||||
}
|
||||
text = "";
|
||||
}
|
||||
@@ -290,6 +286,11 @@ namespace ts {
|
||||
return resolutions;
|
||||
}
|
||||
|
||||
interface DiagnosticCache {
|
||||
perFile?: FileMap<Diagnostic[]>;
|
||||
allDiagnostics?: Diagnostic[];
|
||||
}
|
||||
|
||||
export function createProgram(rootNames: string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program): Program {
|
||||
let program: Program;
|
||||
let files: SourceFile[] = [];
|
||||
@@ -298,6 +299,9 @@ namespace ts {
|
||||
let noDiagnosticsTypeChecker: TypeChecker;
|
||||
let classifiableNames: Map<string>;
|
||||
|
||||
const cachedSemanticDiagnosticsForFile: DiagnosticCache = {};
|
||||
const cachedDeclarationDiagnosticsForFile: DiagnosticCache = {};
|
||||
|
||||
let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective>();
|
||||
let fileProcessingDiagnostics = createDiagnosticCollection();
|
||||
|
||||
@@ -439,7 +443,7 @@ namespace ts {
|
||||
|
||||
function getCommonSourceDirectory() {
|
||||
if (commonSourceDirectory === undefined) {
|
||||
const emittedFiles = filterSourceFilesInDirectory(files, isSourceFileFromExternalLibrary);
|
||||
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary));
|
||||
if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) {
|
||||
// If a rootDir is specified and is valid use it as the commonSourceDirectory
|
||||
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
|
||||
@@ -754,15 +758,15 @@ namespace ts {
|
||||
return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false));
|
||||
}
|
||||
|
||||
function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean): EmitResult {
|
||||
return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles));
|
||||
function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers): EmitResult {
|
||||
return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers));
|
||||
}
|
||||
|
||||
function isEmitBlocked(emitFileName: string): boolean {
|
||||
return hasEmitBlockingDiagnostics.contains(toPath(emitFileName, currentDirectory, getCanonicalFileName));
|
||||
}
|
||||
|
||||
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean): EmitResult {
|
||||
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
|
||||
let declarationDiagnostics: Diagnostic[] = [];
|
||||
|
||||
if (options.noEmit) {
|
||||
@@ -804,11 +808,13 @@ namespace ts {
|
||||
|
||||
performance.mark("beforeEmit");
|
||||
|
||||
const transformers = emitOnlyDtsFiles ? [] : getTransformers(options, customTransformers);
|
||||
const emitResult = emitFiles(
|
||||
emitResolver,
|
||||
getEmitHost(writeFileCallback),
|
||||
sourceFile,
|
||||
emitOnlyDtsFiles);
|
||||
emitOnlyDtsFiles,
|
||||
transformers);
|
||||
|
||||
performance.mark("afterEmit");
|
||||
performance.measure("Emit", "beforeEmit", "afterEmit");
|
||||
@@ -897,22 +903,51 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedSemanticDiagnosticsForFile, getSemanticDiagnosticsForFileNoCache);
|
||||
}
|
||||
|
||||
function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
return runWithCancellationToken(() => {
|
||||
const typeChecker = getDiagnosticsProducingTypeChecker();
|
||||
|
||||
Debug.assert(!!sourceFile.bindDiagnostics);
|
||||
const bindDiagnostics = sourceFile.bindDiagnostics;
|
||||
// For JavaScript files, we don't want to report semantic errors.
|
||||
// Instead, we'll report errors for using TypeScript-only constructs from within a
|
||||
// JavaScript file when we get syntactic diagnostics for the file.
|
||||
const checkDiagnostics = isSourceFileJavaScript(sourceFile) ? [] : typeChecker.getDiagnostics(sourceFile, cancellationToken);
|
||||
// For JavaScript files, we don't want to report semantic errors unless explicitly requested.
|
||||
const includeCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || isCheckJsEnabledForFile(sourceFile, options);
|
||||
const checkDiagnostics = includeCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : [];
|
||||
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
|
||||
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
|
||||
|
||||
return bindDiagnostics.concat(checkDiagnostics, fileProcessingDiagnosticsInFile, programDiagnosticsInFile);
|
||||
const diagnostics = bindDiagnostics.concat(checkDiagnostics, fileProcessingDiagnosticsInFile, programDiagnosticsInFile);
|
||||
return isSourceFileJavaScript(sourceFile)
|
||||
? filter(diagnostics, shouldReportDiagnostic)
|
||||
: diagnostics;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip errors if previous line start with '// @ts-ignore' comment, not counting non-empty non-comment lines
|
||||
*/
|
||||
function shouldReportDiagnostic(diagnostic: Diagnostic) {
|
||||
const { file, start } = diagnostic;
|
||||
const lineStarts = getLineStarts(file);
|
||||
let { line } = computeLineAndCharacterOfPosition(lineStarts, start);
|
||||
while (line > 0) {
|
||||
const previousLineText = file.text.slice(lineStarts[line - 1], lineStarts[line]);
|
||||
const result = ignoreDiagnosticCommentRegEx.exec(previousLineText);
|
||||
if (!result) {
|
||||
// non-empty line
|
||||
return true;
|
||||
}
|
||||
if (result[3]) {
|
||||
// @ts-ignore
|
||||
return false;
|
||||
}
|
||||
line--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getJavaScriptSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
|
||||
return runWithCancellationToken(() => {
|
||||
const diagnostics: Diagnostic[] = [];
|
||||
@@ -1092,7 +1127,11 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
function getDeclarationDiagnosticsWorker(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedDeclarationDiagnosticsForFile, getDeclarationDiagnosticsForFileNoCache);
|
||||
}
|
||||
|
||||
function getDeclarationDiagnosticsForFileNoCache(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken) {
|
||||
return runWithCancellationToken(() => {
|
||||
const resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken);
|
||||
// Don't actually write any files since we're just getting diagnostics.
|
||||
@@ -1100,6 +1139,32 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function getAndCacheDiagnostics(
|
||||
sourceFile: SourceFile | undefined,
|
||||
cancellationToken: CancellationToken,
|
||||
cache: DiagnosticCache,
|
||||
getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken) => Diagnostic[]) {
|
||||
|
||||
const cachedResult = sourceFile
|
||||
? cache.perFile && cache.perFile.get(sourceFile.path)
|
||||
: cache.allDiagnostics;
|
||||
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
const result = getDiagnostics(sourceFile, cancellationToken) || emptyArray;
|
||||
if (sourceFile) {
|
||||
if (!cache.perFile) {
|
||||
cache.perFile = createFileMap<Diagnostic[]>();
|
||||
}
|
||||
cache.perFile.set(sourceFile.path, result);
|
||||
}
|
||||
else {
|
||||
cache.allDiagnostics = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
return isDeclarationFile(sourceFile) ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken);
|
||||
}
|
||||
@@ -1152,13 +1217,10 @@ namespace ts {
|
||||
&& (options.isolatedModules || isExternalModuleFile)
|
||||
&& !file.isDeclarationFile) {
|
||||
// synthesize 'import "tslib"' declaration
|
||||
const externalHelpersModuleReference = <StringLiteral>createSynthesizedNode(SyntaxKind.StringLiteral);
|
||||
externalHelpersModuleReference.text = externalHelpersModuleNameText;
|
||||
const importDecl = createSynthesizedNode(SyntaxKind.ImportDeclaration);
|
||||
|
||||
importDecl.parent = file;
|
||||
const externalHelpersModuleReference = createLiteral(externalHelpersModuleNameText);
|
||||
const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined);
|
||||
externalHelpersModuleReference.parent = importDecl;
|
||||
|
||||
importDecl.parent = file;
|
||||
imports = [externalHelpersModuleReference];
|
||||
}
|
||||
|
||||
@@ -1229,7 +1291,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function collectRequireCalls(node: Node): void {
|
||||
if (isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) {
|
||||
if (isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) {
|
||||
(imports || (imports = [])).push(<StringLiteral>(<CallExpression>node).arguments[0]);
|
||||
}
|
||||
else {
|
||||
@@ -1631,7 +1693,7 @@ namespace ts {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"));
|
||||
}
|
||||
|
||||
if (options.noImplicitUseStrict && options.alwaysStrict) {
|
||||
if (options.noImplicitUseStrict && (options.alwaysStrict === undefined ? options.strict : options.alwaysStrict)) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"));
|
||||
}
|
||||
|
||||
@@ -1686,6 +1748,10 @@ namespace ts {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"));
|
||||
}
|
||||
|
||||
if (options.checkJs && !options.allowJs) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs"));
|
||||
}
|
||||
|
||||
if (options.emitDecoratorMetadata &&
|
||||
!options.experimentalDecorators) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"));
|
||||
@@ -1707,7 +1773,7 @@ namespace ts {
|
||||
if (!options.noEmit && !options.suppressOutputPathCheck) {
|
||||
const emitHost = getEmitHost();
|
||||
const emitFilesSeen = createFileMap<boolean>(!host.useCaseSensitiveFileNames() ? key => key.toLocaleLowerCase() : undefined);
|
||||
forEachExpectedEmitFile(emitHost, (emitFileNames) => {
|
||||
forEachEmittedFile(emitHost, (emitFileNames) => {
|
||||
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
|
||||
verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen);
|
||||
});
|
||||
|
||||
+29
-12
@@ -23,6 +23,8 @@ namespace ts {
|
||||
isIdentifier(): boolean;
|
||||
isReservedWord(): boolean;
|
||||
isUnterminated(): boolean;
|
||||
/* @internal */
|
||||
getNumericLiteralFlags(): NumericLiteralFlags;
|
||||
reScanGreaterToken(): SyntaxKind;
|
||||
reScanSlashToken(): SyntaxKind;
|
||||
reScanTemplateToken(): SyntaxKind;
|
||||
@@ -333,7 +335,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getLineStarts(sourceFile: SourceFile): number[] {
|
||||
export function getLineStarts(sourceFile: SourceFileLike): number[] {
|
||||
return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text));
|
||||
}
|
||||
|
||||
@@ -608,10 +610,10 @@ namespace ts {
|
||||
* @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy
|
||||
* return value of the callback.
|
||||
*/
|
||||
function iterateCommentRanges<T, U>(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial?: U): U {
|
||||
function iterateCommentRanges<T, U>(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial?: U): U {
|
||||
let pendingPos: number;
|
||||
let pendingEnd: number;
|
||||
let pendingKind: SyntaxKind;
|
||||
let pendingKind: CommentKind;
|
||||
let pendingHasTrailingNewLine: boolean;
|
||||
let hasPendingCommentRange = false;
|
||||
let collecting = trailing || pos === 0;
|
||||
@@ -707,37 +709,37 @@ namespace ts {
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
export function forEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) {
|
||||
export function forEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) {
|
||||
return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state);
|
||||
}
|
||||
|
||||
export function forEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) {
|
||||
export function forEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) {
|
||||
return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state);
|
||||
}
|
||||
|
||||
export function reduceEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
|
||||
export function reduceEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
|
||||
return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial);
|
||||
}
|
||||
|
||||
export function reduceEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
|
||||
export function reduceEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
|
||||
return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial);
|
||||
}
|
||||
|
||||
function appendCommentRange(pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, _state: any, comments: CommentRange[]) {
|
||||
function appendCommentRange(pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, _state: any, comments: CommentRange[]) {
|
||||
if (!comments) {
|
||||
comments = [];
|
||||
}
|
||||
|
||||
comments.push({ pos, end, hasTrailingNewLine, kind });
|
||||
comments.push({ kind, pos, end, hasTrailingNewLine });
|
||||
return comments;
|
||||
}
|
||||
|
||||
export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined {
|
||||
return reduceEachLeadingCommentRange(text, pos, appendCommentRange, undefined, undefined);
|
||||
return reduceEachLeadingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined);
|
||||
}
|
||||
|
||||
export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined {
|
||||
return reduceEachTrailingCommentRange(text, pos, appendCommentRange, undefined, undefined);
|
||||
return reduceEachTrailingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined);
|
||||
}
|
||||
|
||||
/** Optionally, get the shebang */
|
||||
@@ -799,6 +801,7 @@ namespace ts {
|
||||
let precedingLineBreak: boolean;
|
||||
let hasExtendedUnicodeEscape: boolean;
|
||||
let tokenIsUnterminated: boolean;
|
||||
let numericLiteralFlags: NumericLiteralFlags;
|
||||
|
||||
setText(text, start, length);
|
||||
|
||||
@@ -814,6 +817,7 @@ namespace ts {
|
||||
isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord,
|
||||
isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord,
|
||||
isUnterminated: () => tokenIsUnterminated,
|
||||
getNumericLiteralFlags: () => numericLiteralFlags,
|
||||
reScanGreaterToken,
|
||||
reScanSlashToken,
|
||||
reScanTemplateToken,
|
||||
@@ -850,6 +854,7 @@ namespace ts {
|
||||
let end = pos;
|
||||
if (text.charCodeAt(pos) === CharacterCodes.E || text.charCodeAt(pos) === CharacterCodes.e) {
|
||||
pos++;
|
||||
numericLiteralFlags = NumericLiteralFlags.Scientific;
|
||||
if (text.charCodeAt(pos) === CharacterCodes.plus || text.charCodeAt(pos) === CharacterCodes.minus) pos++;
|
||||
if (isDigit(text.charCodeAt(pos))) {
|
||||
pos++;
|
||||
@@ -1221,6 +1226,7 @@ namespace ts {
|
||||
hasExtendedUnicodeEscape = false;
|
||||
precedingLineBreak = false;
|
||||
tokenIsUnterminated = false;
|
||||
numericLiteralFlags = 0;
|
||||
while (true) {
|
||||
tokenPos = pos;
|
||||
if (pos >= end) {
|
||||
@@ -1419,6 +1425,7 @@ namespace ts {
|
||||
value = 0;
|
||||
}
|
||||
tokenValue = "" + value;
|
||||
numericLiteralFlags = NumericLiteralFlags.HexSpecifier;
|
||||
return token = SyntaxKind.NumericLiteral;
|
||||
}
|
||||
else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) {
|
||||
@@ -1429,6 +1436,7 @@ namespace ts {
|
||||
value = 0;
|
||||
}
|
||||
tokenValue = "" + value;
|
||||
numericLiteralFlags = NumericLiteralFlags.BinarySpecifier;
|
||||
return token = SyntaxKind.NumericLiteral;
|
||||
}
|
||||
else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) {
|
||||
@@ -1439,11 +1447,13 @@ namespace ts {
|
||||
value = 0;
|
||||
}
|
||||
tokenValue = "" + value;
|
||||
numericLiteralFlags = NumericLiteralFlags.OctalSpecifier;
|
||||
return token = SyntaxKind.NumericLiteral;
|
||||
}
|
||||
// Try to parse as an octal
|
||||
if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) {
|
||||
tokenValue = "" + scanOctalDigits();
|
||||
numericLiteralFlags = NumericLiteralFlags.Octal;
|
||||
return token = SyntaxKind.NumericLiteral;
|
||||
}
|
||||
// This fall-through is a deviation from the EcmaScript grammar. The grammar says that a leading zero
|
||||
@@ -1716,7 +1726,14 @@ namespace ts {
|
||||
while (pos < end) {
|
||||
pos++;
|
||||
char = text.charCodeAt(pos);
|
||||
if ((char === CharacterCodes.openBrace) || (char === CharacterCodes.lessThan)) {
|
||||
if (char === CharacterCodes.openBrace) {
|
||||
break;
|
||||
}
|
||||
if (char === CharacterCodes.lessThan) {
|
||||
if (isConflictMarkerTrivia(text, pos)) {
|
||||
pos = scanConflictMarkerTrivia(text, pos, error);
|
||||
return token = SyntaxKind.ConflictMarkerTrivia;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-15
@@ -8,10 +8,9 @@ namespace ts {
|
||||
*
|
||||
* @param filePath The path to the generated output file.
|
||||
* @param sourceMapFilePath The path to the output source map file.
|
||||
* @param sourceFiles The input source files for the program.
|
||||
* @param isBundledEmit A value indicating whether the generated output file is a bundle.
|
||||
* @param sourceFileOrBundle The input source file or bundle for the program.
|
||||
*/
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
|
||||
initialize(filePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle): void;
|
||||
|
||||
/**
|
||||
* Reset the SourceMapWriter to an empty state.
|
||||
@@ -38,11 +37,11 @@ namespace ts {
|
||||
/**
|
||||
* Emits a node with possible leading and trailing source maps.
|
||||
*
|
||||
* @param emitContext The current emit context
|
||||
* @param hint The current emit context
|
||||
* @param node The node to emit.
|
||||
* @param emitCallback The callback used to emit the node.
|
||||
*/
|
||||
emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
|
||||
emitNodeWithSourceMap(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
|
||||
|
||||
/**
|
||||
* Emits a token of a node node with possible leading and trailing source maps.
|
||||
@@ -115,10 +114,9 @@ namespace ts {
|
||||
*
|
||||
* @param filePath The path to the generated output file.
|
||||
* @param sourceMapFilePath The path to the output source map file.
|
||||
* @param sourceFiles The input source files for the program.
|
||||
* @param isBundledEmit A value indicating whether the generated output file is a bundle.
|
||||
* @param sourceFileOrBundle The input source file or bundle for the program.
|
||||
*/
|
||||
function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
|
||||
function initialize(filePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
@@ -161,11 +159,10 @@ namespace ts {
|
||||
|
||||
if (compilerOptions.mapRoot) {
|
||||
sourceMapDir = normalizeSlashes(compilerOptions.mapRoot);
|
||||
if (!isBundledEmit) { // emitting single module file
|
||||
Debug.assert(sourceFiles.length === 1);
|
||||
if (sourceFileOrBundle.kind === SyntaxKind.SourceFile) { // emitting single module file
|
||||
// For modules or multiple emit files the mapRoot will have directory structure like the sources
|
||||
// So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
|
||||
sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir));
|
||||
sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFileOrBundle, host, sourceMapDir));
|
||||
}
|
||||
|
||||
if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) {
|
||||
@@ -311,12 +308,13 @@ namespace ts {
|
||||
/**
|
||||
* Emits a node with possible leading and trailing source maps.
|
||||
*
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to emit.
|
||||
* @param emitCallback The callback used to emit the node.
|
||||
*/
|
||||
function emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
function emitNodeWithSourceMap(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
|
||||
if (disabled) {
|
||||
return emitCallback(emitContext, node);
|
||||
return emitCallback(hint, node);
|
||||
}
|
||||
|
||||
if (node) {
|
||||
@@ -332,11 +330,11 @@ namespace ts {
|
||||
|
||||
if (emitFlags & EmitFlags.NoNestedSourceMaps) {
|
||||
disabled = true;
|
||||
emitCallback(emitContext, node);
|
||||
emitCallback(hint, node);
|
||||
disabled = false;
|
||||
}
|
||||
else {
|
||||
emitCallback(emitContext, node);
|
||||
emitCallback(hint, node);
|
||||
}
|
||||
|
||||
if (node.kind !== SyntaxKind.NotEmittedStatement
|
||||
|
||||
+29
-167
@@ -1,4 +1,7 @@
|
||||
/// <reference path="core.ts"/>
|
||||
/// <reference path="core.ts"/>
|
||||
|
||||
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
|
||||
declare function clearTimeout(handle: any): void;
|
||||
|
||||
namespace ts {
|
||||
export type FileWatcherCallback = (fileName: string, removed?: boolean) => void;
|
||||
@@ -51,19 +54,27 @@ namespace ts {
|
||||
referenceCount: number;
|
||||
}
|
||||
|
||||
declare var require: any;
|
||||
declare var process: any;
|
||||
declare var global: any;
|
||||
declare var __filename: string;
|
||||
declare const require: any;
|
||||
declare const process: any;
|
||||
declare const global: any;
|
||||
declare const __filename: string;
|
||||
|
||||
declare class Enumerator {
|
||||
public atEnd(): boolean;
|
||||
public moveNext(): boolean;
|
||||
public item(): any;
|
||||
constructor(o: any);
|
||||
export function getNodeMajorVersion() {
|
||||
if (typeof process === "undefined") {
|
||||
return undefined;
|
||||
}
|
||||
const version: string = process.version;
|
||||
if (!version) {
|
||||
return undefined;
|
||||
}
|
||||
const dot = version.indexOf(".");
|
||||
if (dot === -1) {
|
||||
return undefined;
|
||||
}
|
||||
return parseInt(version.substring(1, dot));
|
||||
}
|
||||
|
||||
declare var ChakraHost: {
|
||||
declare const ChakraHost: {
|
||||
args: string[];
|
||||
currentDirectory: string;
|
||||
executingFile: string;
|
||||
@@ -86,152 +97,6 @@ namespace ts {
|
||||
};
|
||||
|
||||
export let sys: System = (function() {
|
||||
|
||||
function getWScriptSystem(): System {
|
||||
|
||||
const fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||
const shell = new ActiveXObject("WScript.Shell");
|
||||
|
||||
const fileStream = new ActiveXObject("ADODB.Stream");
|
||||
fileStream.Type = 2 /*text*/;
|
||||
|
||||
const binaryStream = new ActiveXObject("ADODB.Stream");
|
||||
binaryStream.Type = 1 /*binary*/;
|
||||
|
||||
const args: string[] = [];
|
||||
for (let i = 0; i < WScript.Arguments.length; i++) {
|
||||
args[i] = WScript.Arguments.Item(i);
|
||||
}
|
||||
|
||||
function readFile(fileName: string, encoding?: string): string {
|
||||
if (!fso.FileExists(fileName)) {
|
||||
return undefined;
|
||||
}
|
||||
fileStream.Open();
|
||||
try {
|
||||
if (encoding) {
|
||||
fileStream.Charset = encoding;
|
||||
fileStream.LoadFromFile(fileName);
|
||||
}
|
||||
else {
|
||||
// Load file and read the first two bytes into a string with no interpretation
|
||||
fileStream.Charset = "x-ansi";
|
||||
fileStream.LoadFromFile(fileName);
|
||||
const bom = fileStream.ReadText(2) || "";
|
||||
// Position must be at 0 before encoding can be changed
|
||||
fileStream.Position = 0;
|
||||
// [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
|
||||
fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
|
||||
}
|
||||
// ReadText method always strips byte order mark from resulting string
|
||||
return fileStream.ReadText();
|
||||
}
|
||||
catch (e) {
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
|
||||
fileStream.Open();
|
||||
binaryStream.Open();
|
||||
try {
|
||||
// Write characters in UTF-8 encoding
|
||||
fileStream.Charset = "utf-8";
|
||||
fileStream.WriteText(data);
|
||||
// If we don't want the BOM, then skip it by setting the starting location to 3 (size of BOM).
|
||||
// If not, start from position 0, as the BOM will be added automatically when charset==utf8.
|
||||
if (writeByteOrderMark) {
|
||||
fileStream.Position = 0;
|
||||
}
|
||||
else {
|
||||
fileStream.Position = 3;
|
||||
}
|
||||
fileStream.CopyTo(binaryStream);
|
||||
binaryStream.SaveToFile(fileName, 2 /*overwrite*/);
|
||||
}
|
||||
finally {
|
||||
binaryStream.Close();
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
function getNames(collection: any): string[] {
|
||||
const result: string[] = [];
|
||||
for (const e = new Enumerator(collection); !e.atEnd(); e.moveNext()) {
|
||||
result.push(e.item().Name);
|
||||
}
|
||||
return result.sort();
|
||||
}
|
||||
|
||||
function getDirectories(path: string): string[] {
|
||||
const folder = fso.GetFolder(path);
|
||||
return getNames(folder.subfolders);
|
||||
}
|
||||
|
||||
function getAccessibleFileSystemEntries(path: string): FileSystemEntries {
|
||||
try {
|
||||
const folder = fso.GetFolder(path || ".");
|
||||
const files = getNames(folder.files);
|
||||
const directories = getNames(folder.subfolders);
|
||||
return { files, directories };
|
||||
}
|
||||
catch (e) {
|
||||
return { files: [], directories: [] };
|
||||
}
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extensions?: string[], excludes?: string[], includes?: string[]): string[] {
|
||||
return matchFiles(path, extensions, excludes, includes, /*useCaseSensitiveFileNames*/ false, shell.CurrentDirectory, getAccessibleFileSystemEntries);
|
||||
}
|
||||
|
||||
const wscriptSystem: System = {
|
||||
args,
|
||||
newLine: "\r\n",
|
||||
useCaseSensitiveFileNames: false,
|
||||
write(s: string): void {
|
||||
WScript.StdOut.Write(s);
|
||||
},
|
||||
readFile,
|
||||
writeFile,
|
||||
resolvePath(path: string): string {
|
||||
return fso.GetAbsolutePathName(path);
|
||||
},
|
||||
fileExists(path: string): boolean {
|
||||
return fso.FileExists(path);
|
||||
},
|
||||
directoryExists(path: string) {
|
||||
return fso.FolderExists(path);
|
||||
},
|
||||
createDirectory(directoryName: string) {
|
||||
if (!wscriptSystem.directoryExists(directoryName)) {
|
||||
fso.CreateFolder(directoryName);
|
||||
}
|
||||
},
|
||||
getExecutingFilePath() {
|
||||
return WScript.ScriptFullName;
|
||||
},
|
||||
getCurrentDirectory() {
|
||||
return shell.CurrentDirectory;
|
||||
},
|
||||
getDirectories,
|
||||
getEnvironmentVariable(name: string) {
|
||||
return new ActiveXObject("WScript.Shell").ExpandEnvironmentStrings(`%${name}%`);
|
||||
},
|
||||
readDirectory,
|
||||
exit(exitCode?: number): void {
|
||||
try {
|
||||
WScript.Quit(exitCode);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
return wscriptSystem;
|
||||
}
|
||||
|
||||
function getNodeSystem(): System {
|
||||
const _fs = require("fs");
|
||||
const _path = require("path");
|
||||
@@ -312,9 +177,8 @@ namespace ts {
|
||||
}
|
||||
const watchedFileSet = createWatchedFileSet();
|
||||
|
||||
function isNode4OrLater(): boolean {
|
||||
return parseInt(process.version.charAt(1)) >= 4;
|
||||
}
|
||||
const nodeVersion = getNodeMajorVersion();
|
||||
const isNode4OrLater = nodeVersion >= 4;
|
||||
|
||||
function isFileSystemCaseSensitive(): boolean {
|
||||
// win32\win64 are case insensitive platforms
|
||||
@@ -338,7 +202,7 @@ namespace ts {
|
||||
if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) {
|
||||
// Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js,
|
||||
// flip all byte pairs and treat as little endian.
|
||||
len &= ~1;
|
||||
len &= ~1; // Round down to a multiple of 2
|
||||
for (let i = 0; i < len; i += 2) {
|
||||
const temp = buffer[i];
|
||||
buffer[i] = buffer[i + 1];
|
||||
@@ -368,7 +232,7 @@ namespace ts {
|
||||
|
||||
try {
|
||||
fd = _fs.openSync(fileName, "w");
|
||||
_fs.writeSync(fd, data, undefined, "utf8");
|
||||
_fs.writeSync(fd, data, /*position*/ undefined, "utf8");
|
||||
}
|
||||
finally {
|
||||
if (fd !== undefined) {
|
||||
@@ -483,10 +347,11 @@ namespace ts {
|
||||
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
|
||||
let options: any;
|
||||
if (!directoryExists(directoryName)) {
|
||||
// do nothing if target folder does not exist
|
||||
return noOpFileWatcher;
|
||||
}
|
||||
|
||||
if (isNode4OrLater() && (process.platform === "win32" || process.platform === "darwin")) {
|
||||
if (isNode4OrLater && (process.platform === "win32" || process.platform === "darwin")) {
|
||||
options = { persistent: true, recursive: !!recursive };
|
||||
}
|
||||
else {
|
||||
@@ -503,7 +368,7 @@ namespace ts {
|
||||
if (eventName === "rename") {
|
||||
// When deleting a file, the passed baseFileName is null
|
||||
callback(!relativeFileName ? relativeFileName : normalizePath(combinePaths(directoryName, relativeFileName)));
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
@@ -628,9 +493,6 @@ namespace ts {
|
||||
if (typeof ChakraHost !== "undefined") {
|
||||
sys = getChakraSystem();
|
||||
}
|
||||
else if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
|
||||
sys = getWScriptSystem();
|
||||
}
|
||||
else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") {
|
||||
// process and process.nextTick checks if current environment is node-like
|
||||
// process.browser check excludes webpack and browserify
|
||||
|
||||
+109
-59
@@ -1,4 +1,4 @@
|
||||
/// <reference path="visitor.ts" />
|
||||
/// <reference path="visitor.ts" />
|
||||
/// <reference path="transformers/ts.ts" />
|
||||
/// <reference path="transformers/jsx.ts" />
|
||||
/// <reference path="transformers/esnext.ts" />
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
function getModuleTransformer(moduleKind: ModuleKind): Transformer {
|
||||
function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<SourceFile> {
|
||||
switch (moduleKind) {
|
||||
case ModuleKind.ES2015:
|
||||
return transformES2015Module;
|
||||
@@ -24,16 +24,25 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const enum TransformationState {
|
||||
Uninitialized,
|
||||
Initialized,
|
||||
Completed,
|
||||
Disposed
|
||||
}
|
||||
|
||||
const enum SyntaxKindFeatureFlags {
|
||||
Substitution = 1 << 0,
|
||||
EmitNotifications = 1 << 1,
|
||||
}
|
||||
|
||||
export function getTransformers(compilerOptions: CompilerOptions) {
|
||||
export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers) {
|
||||
const jsx = compilerOptions.jsx;
|
||||
const languageVersion = getEmitScriptTarget(compilerOptions);
|
||||
const moduleKind = getEmitModuleKind(compilerOptions);
|
||||
const transformers: Transformer[] = [];
|
||||
const transformers: TransformerFactory<SourceFile>[] = [];
|
||||
|
||||
addRange(transformers, customTransformers && customTransformers.before);
|
||||
|
||||
transformers.push(transformTypeScript);
|
||||
|
||||
@@ -66,6 +75,8 @@ namespace ts {
|
||||
transformers.push(transformES5);
|
||||
}
|
||||
|
||||
addRange(transformers, customTransformers && customTransformers.after);
|
||||
|
||||
return transformers;
|
||||
}
|
||||
|
||||
@@ -73,28 +84,29 @@ namespace ts {
|
||||
* Transforms an array of SourceFiles by passing them through each transformer.
|
||||
*
|
||||
* @param resolver The emit resolver provided by the checker.
|
||||
* @param host The emit host.
|
||||
* @param sourceFiles An array of source files
|
||||
* @param transforms An array of Transformers.
|
||||
* @param host The emit host object used to interact with the file system.
|
||||
* @param options Compiler options to surface in the `TransformationContext`.
|
||||
* @param nodes An array of nodes to transform.
|
||||
* @param transforms An array of `TransformerFactory` callbacks.
|
||||
* @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files.
|
||||
*/
|
||||
export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]): TransformationResult {
|
||||
export function transformNodes<T extends Node>(resolver: EmitResolver, host: EmitHost, options: CompilerOptions, nodes: T[], transformers: TransformerFactory<T>[], allowDtsFiles: boolean): TransformationResult<T> {
|
||||
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
|
||||
|
||||
let lexicalEnvironmentDisabled = false;
|
||||
|
||||
let lexicalEnvironmentVariableDeclarations: VariableDeclaration[];
|
||||
let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[];
|
||||
let lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
|
||||
let lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
|
||||
let lexicalEnvironmentStackOffset = 0;
|
||||
let lexicalEnvironmentSuspended = false;
|
||||
|
||||
let emitHelpers: EmitHelper[];
|
||||
let onSubstituteNode: TransformationContext["onSubstituteNode"] = (_, node) => node;
|
||||
let onEmitNode: TransformationContext["onEmitNode"] = (hint, node, callback) => callback(hint, node);
|
||||
let state = TransformationState.Uninitialized;
|
||||
|
||||
// The transformation context is provided to each transformer as part of transformer
|
||||
// initialization.
|
||||
const context: TransformationContext = {
|
||||
getCompilerOptions: () => host.getCompilerOptions(),
|
||||
getCompilerOptions: () => options,
|
||||
getEmitResolver: () => resolver,
|
||||
getEmitHost: () => host,
|
||||
startLexicalEnvironment,
|
||||
@@ -105,46 +117,62 @@ namespace ts {
|
||||
hoistFunctionDeclaration,
|
||||
requestEmitHelper,
|
||||
readEmitHelpers,
|
||||
onSubstituteNode: (_emitContext, node) => node,
|
||||
enableSubstitution,
|
||||
isSubstitutionEnabled,
|
||||
onEmitNode: (node, emitContext, emitCallback) => emitCallback(node, emitContext),
|
||||
enableEmitNotification,
|
||||
isEmitNotificationEnabled
|
||||
isSubstitutionEnabled,
|
||||
isEmitNotificationEnabled,
|
||||
get onSubstituteNode() { return onSubstituteNode; },
|
||||
set onSubstituteNode(value) {
|
||||
Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed.");
|
||||
Debug.assert(value !== undefined, "Value must not be 'undefined'");
|
||||
onSubstituteNode = value;
|
||||
},
|
||||
get onEmitNode() { return onEmitNode; },
|
||||
set onEmitNode(value) {
|
||||
Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed.");
|
||||
Debug.assert(value !== undefined, "Value must not be 'undefined'");
|
||||
onEmitNode = value;
|
||||
}
|
||||
};
|
||||
|
||||
// Ensure the parse tree is clean before applying transformations
|
||||
for (const node of nodes) {
|
||||
disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node)));
|
||||
}
|
||||
|
||||
performance.mark("beforeTransform");
|
||||
|
||||
// Chain together and initialize each transformer.
|
||||
const transformation = chain(...transformers)(context);
|
||||
|
||||
// Transform each source file.
|
||||
const transformed = map(sourceFiles, transformSourceFile);
|
||||
// prevent modification of transformation hooks.
|
||||
state = TransformationState.Initialized;
|
||||
|
||||
// Disable modification of the lexical environment.
|
||||
lexicalEnvironmentDisabled = true;
|
||||
// Transform each node.
|
||||
const transformed = map(nodes, allowDtsFiles ? transformation : transformRoot);
|
||||
|
||||
// prevent modification of the lexical environment.
|
||||
state = TransformationState.Completed;
|
||||
|
||||
performance.mark("afterTransform");
|
||||
performance.measure("transformTime", "beforeTransform", "afterTransform");
|
||||
|
||||
return {
|
||||
transformed,
|
||||
emitNodeWithSubstitution,
|
||||
emitNodeWithNotification
|
||||
substituteNode,
|
||||
emitNodeWithNotification,
|
||||
dispose
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms a source file.
|
||||
*
|
||||
* @param sourceFile The source file to transform.
|
||||
*/
|
||||
function transformSourceFile(sourceFile: SourceFile) {
|
||||
if (isDeclarationFile(sourceFile)) {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
return transformation(sourceFile);
|
||||
function transformRoot(node: T) {
|
||||
return node && (!isSourceFile(node) || !isDeclarationFile(node)) ? transformation(node) : node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables expression substitutions in the pretty printer for the provided SyntaxKind.
|
||||
*/
|
||||
function enableSubstitution(kind: SyntaxKind) {
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed.");
|
||||
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.Substitution;
|
||||
}
|
||||
|
||||
@@ -159,28 +187,20 @@ namespace ts {
|
||||
/**
|
||||
* Emits a node with possible substitution.
|
||||
*
|
||||
* @param emitContext The current emit context.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to emit.
|
||||
* @param emitCallback The callback used to emit the node or its substitute.
|
||||
*/
|
||||
function emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
if (node) {
|
||||
if (isSubstitutionEnabled(node)) {
|
||||
const substitute = context.onSubstituteNode(emitContext, node);
|
||||
if (substitute && substitute !== node) {
|
||||
emitCallback(emitContext, substitute);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
emitCallback(emitContext, node);
|
||||
}
|
||||
function substituteNode(hint: EmitHint, node: Node) {
|
||||
Debug.assert(state < TransformationState.Disposed, "Cannot substitute a node after the result is disposed.");
|
||||
return node && isSubstitutionEnabled(node) && onSubstituteNode(hint, node) || node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables before/after emit notifications in the pretty printer for the provided SyntaxKind.
|
||||
*/
|
||||
function enableEmitNotification(kind: SyntaxKind) {
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed.");
|
||||
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.EmitNotifications;
|
||||
}
|
||||
|
||||
@@ -196,17 +216,18 @@ namespace ts {
|
||||
/**
|
||||
* Emits a node with possible emit notification.
|
||||
*
|
||||
* @param emitContext The current emit context.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to emit.
|
||||
* @param emitCallback The callback used to emit the node.
|
||||
*/
|
||||
function emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
function emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
|
||||
Debug.assert(state < TransformationState.Disposed, "Cannot invoke TransformationResult callbacks after the result is disposed.");
|
||||
if (node) {
|
||||
if (isEmitNotificationEnabled(node)) {
|
||||
context.onEmitNode(emitContext, node, emitCallback);
|
||||
onEmitNode(hint, node, emitCallback);
|
||||
}
|
||||
else {
|
||||
emitCallback(emitContext, node);
|
||||
emitCallback(hint, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,7 +236,8 @@ namespace ts {
|
||||
* Records a hoisted variable declaration for the provided name within a lexical environment.
|
||||
*/
|
||||
function hoistVariableDeclaration(name: Identifier): void {
|
||||
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
|
||||
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
|
||||
const decl = createVariableDeclaration(name);
|
||||
if (!lexicalEnvironmentVariableDeclarations) {
|
||||
lexicalEnvironmentVariableDeclarations = [decl];
|
||||
@@ -229,7 +251,8 @@ namespace ts {
|
||||
* Records a hoisted function declaration within a lexical environment.
|
||||
*/
|
||||
function hoistFunctionDeclaration(func: FunctionDeclaration): void {
|
||||
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
|
||||
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
|
||||
if (!lexicalEnvironmentFunctionDeclarations) {
|
||||
lexicalEnvironmentFunctionDeclarations = [func];
|
||||
}
|
||||
@@ -243,7 +266,8 @@ namespace ts {
|
||||
* are pushed onto a stack, and the related storage variables are reset.
|
||||
*/
|
||||
function startLexicalEnvironment(): void {
|
||||
Debug.assert(!lexicalEnvironmentDisabled, "Cannot start a lexical environment during the print phase.");
|
||||
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
|
||||
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended.");
|
||||
|
||||
// Save the current lexical environment. Rather than resizing the array we adjust the
|
||||
@@ -259,14 +283,16 @@ namespace ts {
|
||||
|
||||
/** Suspends the current lexical environment, usually after visiting a parameter list. */
|
||||
function suspendLexicalEnvironment(): void {
|
||||
Debug.assert(!lexicalEnvironmentDisabled, "Cannot suspend a lexical environment during the print phase.");
|
||||
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
|
||||
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is already suspended.");
|
||||
lexicalEnvironmentSuspended = true;
|
||||
}
|
||||
|
||||
/** Resumes a suspended lexical environment, usually before visiting a function body. */
|
||||
function resumeLexicalEnvironment(): void {
|
||||
Debug.assert(!lexicalEnvironmentDisabled, "Cannot resume a lexical environment during the print phase.");
|
||||
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
|
||||
Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended.");
|
||||
lexicalEnvironmentSuspended = false;
|
||||
}
|
||||
@@ -276,7 +302,8 @@ namespace ts {
|
||||
* any hoisted declarations added in this environment are returned.
|
||||
*/
|
||||
function endLexicalEnvironment(): Statement[] {
|
||||
Debug.assert(!lexicalEnvironmentDisabled, "Cannot end a lexical environment during the print phase.");
|
||||
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
|
||||
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended.");
|
||||
|
||||
let statements: Statement[];
|
||||
@@ -312,16 +339,39 @@ namespace ts {
|
||||
}
|
||||
|
||||
function requestEmitHelper(helper: EmitHelper): void {
|
||||
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
|
||||
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization.");
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed.");
|
||||
Debug.assert(!helper.scoped, "Cannot request a scoped emit helper.");
|
||||
emitHelpers = append(emitHelpers, helper);
|
||||
}
|
||||
|
||||
function readEmitHelpers(): EmitHelper[] | undefined {
|
||||
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
|
||||
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization.");
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed.");
|
||||
const helpers = emitHelpers;
|
||||
emitHelpers = undefined;
|
||||
return helpers;
|
||||
}
|
||||
|
||||
function dispose() {
|
||||
if (state < TransformationState.Disposed) {
|
||||
// Clean up emit nodes on parse tree
|
||||
for (const node of nodes) {
|
||||
disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node)));
|
||||
}
|
||||
|
||||
// Release references to external entries for GC purposes.
|
||||
lexicalEnvironmentVariableDeclarations = undefined;
|
||||
lexicalEnvironmentVariableDeclarationsStack = undefined;
|
||||
lexicalEnvironmentFunctionDeclarations = undefined;
|
||||
lexicalEnvironmentFunctionDeclarationsStack = undefined;
|
||||
onSubstituteNode = undefined;
|
||||
onEmitNode = undefined;
|
||||
emitHelpers = undefined;
|
||||
|
||||
// Prevent further use of the transformation result.
|
||||
state = TransformationState.Disposed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace ts {
|
||||
interface FlattenContext {
|
||||
context: TransformationContext;
|
||||
level: FlattenLevel;
|
||||
downlevelIteration: boolean;
|
||||
hoistTempVariables: boolean;
|
||||
emitExpression: (value: Expression) => void;
|
||||
emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) => void;
|
||||
@@ -42,7 +43,7 @@ namespace ts {
|
||||
let value: Expression;
|
||||
if (isDestructuringAssignment(node)) {
|
||||
value = node.right;
|
||||
while (isEmptyObjectLiteralOrArrayLiteral(node.left)) {
|
||||
while (isEmptyArrayLiteral(node.left) || isEmptyObjectLiteral(node.left)) {
|
||||
if (isDestructuringAssignment(value)) {
|
||||
location = node = value;
|
||||
value = node.right;
|
||||
@@ -57,6 +58,7 @@ namespace ts {
|
||||
const flattenContext: FlattenContext = {
|
||||
context,
|
||||
level,
|
||||
downlevelIteration: context.getCompilerOptions().downlevelIteration,
|
||||
hoistTempVariables: true,
|
||||
emitExpression,
|
||||
emitBindingOrAssignment,
|
||||
@@ -112,7 +114,10 @@ namespace ts {
|
||||
Debug.assertNode(target, createAssignmentCallback ? isIdentifier : isExpression);
|
||||
const expression = createAssignmentCallback
|
||||
? createAssignmentCallback(<Identifier>target, value, location)
|
||||
: createAssignment(visitNode(<Expression>target, visitor, isExpression), value, location);
|
||||
: setTextRange(
|
||||
createAssignment(visitNode(<Expression>target, visitor, isExpression), value),
|
||||
location
|
||||
);
|
||||
expression.original = original;
|
||||
emitExpression(expression);
|
||||
}
|
||||
@@ -143,6 +148,7 @@ namespace ts {
|
||||
const flattenContext: FlattenContext = {
|
||||
context,
|
||||
level,
|
||||
downlevelIteration: context.getCompilerOptions().downlevelIteration,
|
||||
hoistTempVariables,
|
||||
emitExpression,
|
||||
emitBindingOrAssignment,
|
||||
@@ -174,9 +180,10 @@ namespace ts {
|
||||
const variable = createVariableDeclaration(
|
||||
name,
|
||||
/*type*/ undefined,
|
||||
pendingExpressions ? inlineExpressions(append(pendingExpressions, value)) : value,
|
||||
location);
|
||||
pendingExpressions ? inlineExpressions(append(pendingExpressions, value)) : value
|
||||
);
|
||||
variable.original = original;
|
||||
setTextRange(variable, location);
|
||||
if (isIdentifier(name)) {
|
||||
setEmitFlags(variable, EmitFlags.NoNestedSourceMaps);
|
||||
}
|
||||
@@ -308,7 +315,23 @@ namespace ts {
|
||||
function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, parent: BindingOrAssignmentElement, pattern: ArrayBindingOrAssignmentPattern, value: Expression, location: TextRange) {
|
||||
const elements = getElementsOfBindingOrAssignmentPattern(pattern);
|
||||
const numElements = elements.length;
|
||||
if (numElements !== 1 && (flattenContext.level < FlattenLevel.ObjectRest || numElements === 0)) {
|
||||
if (flattenContext.level < FlattenLevel.ObjectRest && flattenContext.downlevelIteration) {
|
||||
// Read the elements of the iterable into an array
|
||||
value = ensureIdentifier(
|
||||
flattenContext,
|
||||
createReadHelper(
|
||||
flattenContext.context,
|
||||
value,
|
||||
numElements > 0 && getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1])
|
||||
? undefined
|
||||
: numElements,
|
||||
location
|
||||
),
|
||||
/*reuseIdentifierExpressions*/ false,
|
||||
location
|
||||
);
|
||||
}
|
||||
else if (numElements !== 1 && (flattenContext.level < FlattenLevel.ObjectRest || numElements === 0)) {
|
||||
// For anything other than a single-element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once. Additionally, if we have zero elements
|
||||
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
|
||||
@@ -416,7 +439,7 @@ namespace ts {
|
||||
const temp = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
if (flattenContext.hoistTempVariables) {
|
||||
flattenContext.context.hoistVariableDeclaration(temp);
|
||||
flattenContext.emitExpression(createAssignment(temp, value, location));
|
||||
flattenContext.emitExpression(setTextRange(createAssignment(temp, value), location));
|
||||
}
|
||||
else {
|
||||
flattenContext.emitBindingOrAssignment(temp, value, location, /*original*/ undefined);
|
||||
@@ -444,7 +467,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function makeBindingElement(name: Identifier) {
|
||||
return createBindingElement(/*propertyName*/ undefined, /*dotDotDotToken*/ undefined, name);
|
||||
return createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name);
|
||||
}
|
||||
|
||||
function makeAssignmentElement(name: Identifier) {
|
||||
@@ -467,7 +490,8 @@ namespace ts {
|
||||
};
|
||||
|
||||
/** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement
|
||||
* `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);`*/
|
||||
* `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);`
|
||||
*/
|
||||
function createRestCall(context: TransformationContext, value: Expression, elements: BindingOrAssignmentElement[], computedTempVariables: Expression[], location: TextRange): Expression {
|
||||
context.requestEmitHelper(restHelper);
|
||||
const propertyNames: Expression[] = [];
|
||||
@@ -492,6 +516,15 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
return createCall(getHelperName("__rest"), undefined, [value, createArrayLiteral(propertyNames, location)]);
|
||||
return createCall(
|
||||
getHelperName("__rest"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
value,
|
||||
setTextRange(
|
||||
createArrayLiteral(propertyNames),
|
||||
location
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
+513
-307
File diff suppressed because it is too large
Load Diff
@@ -48,29 +48,37 @@ namespace ts {
|
||||
// Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)`
|
||||
const expressionTemp = createTempVariable(hoistVariableDeclaration);
|
||||
const argumentExpressionTemp = createTempVariable(hoistVariableDeclaration);
|
||||
target = createElementAccess(
|
||||
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
|
||||
createAssignment(argumentExpressionTemp, left.argumentExpression, /*location*/ left.argumentExpression),
|
||||
/*location*/ left
|
||||
target = setTextRange(
|
||||
createElementAccess(
|
||||
setTextRange(createAssignment(expressionTemp, left.expression), left.expression),
|
||||
setTextRange(createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression)
|
||||
),
|
||||
left
|
||||
);
|
||||
value = createElementAccess(
|
||||
expressionTemp,
|
||||
argumentExpressionTemp,
|
||||
/*location*/ left
|
||||
value = setTextRange(
|
||||
createElementAccess(
|
||||
expressionTemp,
|
||||
argumentExpressionTemp
|
||||
),
|
||||
left
|
||||
);
|
||||
}
|
||||
else if (isPropertyAccessExpression(left)) {
|
||||
// Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)`
|
||||
const expressionTemp = createTempVariable(hoistVariableDeclaration);
|
||||
target = createPropertyAccess(
|
||||
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
|
||||
left.name,
|
||||
/*location*/ left
|
||||
target = setTextRange(
|
||||
createPropertyAccess(
|
||||
setTextRange(createAssignment(expressionTemp, left.expression), left.expression),
|
||||
left.name
|
||||
),
|
||||
left
|
||||
);
|
||||
value = createPropertyAccess(
|
||||
expressionTemp,
|
||||
left.name,
|
||||
/*location*/ left
|
||||
value = setTextRange(
|
||||
createPropertyAccess(
|
||||
expressionTemp,
|
||||
left.name
|
||||
),
|
||||
left
|
||||
);
|
||||
}
|
||||
else {
|
||||
@@ -78,7 +86,13 @@ namespace ts {
|
||||
target = left;
|
||||
value = left;
|
||||
}
|
||||
return createAssignment(target, createMathPow(value, right, /*location*/ node), /*location*/ node);
|
||||
return setTextRange(
|
||||
createAssignment(
|
||||
target,
|
||||
createMathPow(value, right, /*location*/ node)
|
||||
),
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
function visitExponentiationExpression(node: BinaryExpression) {
|
||||
|
||||
+118
-132
@@ -14,7 +14,7 @@ namespace ts {
|
||||
const {
|
||||
startLexicalEnvironment,
|
||||
resumeLexicalEnvironment,
|
||||
endLexicalEnvironment,
|
||||
endLexicalEnvironment
|
||||
} = context;
|
||||
|
||||
const resolver = context.getEmitResolver();
|
||||
@@ -34,7 +34,7 @@ namespace ts {
|
||||
* This keeps track of containers where `super` is valid, for use with
|
||||
* just-in-time substitution for `super` expressions inside of async methods.
|
||||
*/
|
||||
let currentSuperContainer: SuperContainer;
|
||||
let enclosingSuperContainerFlags: NodeCheckFlags = 0;
|
||||
|
||||
// Save the previous transformation hooks.
|
||||
const previousOnEmitNode = context.onEmitNode;
|
||||
@@ -71,23 +71,18 @@ namespace ts {
|
||||
return undefined;
|
||||
|
||||
case SyntaxKind.AwaitExpression:
|
||||
// ES2017 'await' expressions must be transformed for targets < ES2017.
|
||||
return visitAwaitExpression(<AwaitExpression>node);
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
// ES2017 method declarations may be 'async'
|
||||
return visitMethodDeclaration(<MethodDeclaration>node);
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
// ES2017 function declarations may be 'async'
|
||||
return visitFunctionDeclaration(<FunctionDeclaration>node);
|
||||
|
||||
case SyntaxKind.FunctionExpression:
|
||||
// ES2017 function expressions may be 'async'
|
||||
return visitFunctionExpression(<FunctionExpression>node);
|
||||
|
||||
case SyntaxKind.ArrowFunction:
|
||||
// ES2017 arrow functions may be 'async'
|
||||
return visitArrowFunction(<ArrowFunction>node);
|
||||
|
||||
default:
|
||||
@@ -104,10 +99,12 @@ namespace ts {
|
||||
*/
|
||||
function visitAwaitExpression(node: AwaitExpression): Expression {
|
||||
return setOriginalNode(
|
||||
createYield(
|
||||
/*asteriskToken*/ undefined,
|
||||
visitNode(node.expression, visitor, isExpression),
|
||||
/*location*/ node
|
||||
setTextRange(
|
||||
createYield(
|
||||
/*asteriskToken*/ undefined,
|
||||
visitNode(node.expression, visitor, isExpression)
|
||||
),
|
||||
node
|
||||
),
|
||||
node
|
||||
);
|
||||
@@ -126,11 +123,13 @@ namespace ts {
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
node.asteriskToken,
|
||||
node.name,
|
||||
/*questionToken*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
isAsyncFunctionLike(node)
|
||||
getFunctionFlags(node) & FunctionFlags.Async
|
||||
? transformAsyncFunctionBody(node)
|
||||
: visitFunctionBody(node.body, visitor, context)
|
||||
);
|
||||
@@ -149,11 +148,12 @@ namespace ts {
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
node.asteriskToken,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
isAsyncFunctionLike(node)
|
||||
getFunctionFlags(node) & FunctionFlags.Async
|
||||
? transformAsyncFunctionBody(node)
|
||||
: visitFunctionBody(node.body, visitor, context)
|
||||
);
|
||||
@@ -168,17 +168,15 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitFunctionExpression(node: FunctionExpression): Expression {
|
||||
if (nodeIsMissing(node.body)) {
|
||||
return createOmittedExpression();
|
||||
}
|
||||
return updateFunctionExpression(
|
||||
node,
|
||||
/*modifiers*/ undefined,
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
node.asteriskToken,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
isAsyncFunctionLike(node)
|
||||
getFunctionFlags(node) & FunctionFlags.Async
|
||||
? transformAsyncFunctionBody(node)
|
||||
: visitFunctionBody(node.body, visitor, context)
|
||||
);
|
||||
@@ -199,7 +197,7 @@ namespace ts {
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
isAsyncFunctionLike(node)
|
||||
getFunctionFlags(node) & FunctionFlags.Async
|
||||
? transformAsyncFunctionBody(node)
|
||||
: visitFunctionBody(node.body, visitor, context)
|
||||
);
|
||||
@@ -224,7 +222,7 @@ namespace ts {
|
||||
|
||||
if (!isArrowFunction) {
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, (<Block>node.body).statements, /*ensureUseStrict*/ false, visitor);
|
||||
const statementOffset = addPrologue(statements, (<Block>node.body).statements, /*ensureUseStrict*/ false, visitor);
|
||||
statements.push(
|
||||
createReturn(
|
||||
createAwaiterHelper(
|
||||
@@ -238,7 +236,8 @@ namespace ts {
|
||||
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
|
||||
const block = createBlock(statements, /*location*/ node.body, /*multiLine*/ true);
|
||||
const block = createBlock(statements, /*multiLine*/ true);
|
||||
setTextRange(block, node.body);
|
||||
|
||||
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
|
||||
// This step isn't needed if we eventually transform this to ES5.
|
||||
@@ -266,7 +265,7 @@ namespace ts {
|
||||
const declarations = endLexicalEnvironment();
|
||||
if (some(declarations)) {
|
||||
const block = convertToFunctionBody(expression);
|
||||
return updateBlock(block, createNodeArray(concatenate(block.statements, declarations), block.statements));
|
||||
return updateBlock(block, setTextRange(createNodeArray(concatenate(block.statements, declarations)), block.statements));
|
||||
}
|
||||
|
||||
return expression;
|
||||
@@ -281,7 +280,7 @@ namespace ts {
|
||||
startLexicalEnvironment();
|
||||
const visited = convertToFunctionBody(visitNode(body, visitor, isConciseBody));
|
||||
const declarations = endLexicalEnvironment();
|
||||
return updateBlock(visited, createNodeArray(concatenate(visited.statements, declarations), visited.statements));
|
||||
return updateBlock(visited, setTextRange(createNodeArray(concatenate(visited.statements, declarations)), visited.statements));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,6 +316,44 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for node emit.
|
||||
*
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to emit.
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
*/
|
||||
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
|
||||
// If we need to support substitutions for `super` in an async method,
|
||||
// we should track it here.
|
||||
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
|
||||
const superContainerFlags = resolver.getNodeCheckFlags(node) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
|
||||
if (superContainerFlags !== enclosingSuperContainerFlags) {
|
||||
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
|
||||
enclosingSuperContainerFlags = superContainerFlags;
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
enclosingSuperContainerFlags = savedEnclosingSuperContainerFlags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to substitute.
|
||||
*/
|
||||
function onSubstituteNode(hint: EmitHint, node: Node) {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (hint === EmitHint.Expression && enclosingSuperContainerFlags) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteExpression(node: Expression) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
@@ -324,62 +361,45 @@ namespace ts {
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
return substituteElementAccessExpression(<ElementAccessExpression>node);
|
||||
case SyntaxKind.CallExpression:
|
||||
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper) {
|
||||
return substituteCallExpression(<CallExpression>node);
|
||||
}
|
||||
break;
|
||||
return substituteCallExpression(<CallExpression>node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
|
||||
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
const flags = getSuperContainerAsyncMethodFlags();
|
||||
if (flags) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
createLiteral(node.name.text),
|
||||
flags,
|
||||
node
|
||||
);
|
||||
}
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
createLiteral(node.name.text),
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteElementAccessExpression(node: ElementAccessExpression) {
|
||||
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
const flags = getSuperContainerAsyncMethodFlags();
|
||||
if (flags) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
node.argumentExpression,
|
||||
flags,
|
||||
node
|
||||
);
|
||||
}
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
node.argumentExpression,
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteCallExpression(node: CallExpression): Expression {
|
||||
const expression = node.expression;
|
||||
if (isSuperProperty(expression)) {
|
||||
const flags = getSuperContainerAsyncMethodFlags();
|
||||
if (flags) {
|
||||
const argumentExpression = isPropertyAccessExpression(expression)
|
||||
? substitutePropertyAccessExpression(expression)
|
||||
: substituteElementAccessExpression(expression);
|
||||
return createCall(
|
||||
createPropertyAccess(argumentExpression, "call"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
...node.arguments
|
||||
]
|
||||
);
|
||||
}
|
||||
const argumentExpression = isPropertyAccessExpression(expression)
|
||||
? substitutePropertyAccessExpression(expression)
|
||||
: substituteElementAccessExpression(expression);
|
||||
return createCall(
|
||||
createPropertyAccess(argumentExpression, "call"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
...node.arguments
|
||||
]
|
||||
);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
@@ -393,72 +413,51 @@ namespace ts {
|
||||
|| kind === SyntaxKind.SetAccessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for node emit.
|
||||
*
|
||||
* @param node The node to emit.
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
*/
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
|
||||
// If we need to support substitutions for `super` in an async method,
|
||||
// we should track it here.
|
||||
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
|
||||
const savedCurrentSuperContainer = currentSuperContainer;
|
||||
currentSuperContainer = node;
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
currentSuperContainer = savedCurrentSuperContainer;
|
||||
function createSuperAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
|
||||
if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
createCall(
|
||||
createIdentifier("_super"),
|
||||
/*typeArguments*/ undefined,
|
||||
[argumentExpression]
|
||||
),
|
||||
"value"
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
else {
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param node The node to substitute.
|
||||
* @param isExpression A value indicating whether the node is to be used in an expression
|
||||
* position.
|
||||
*/
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function createSuperAccessInAsyncMethod(argumentExpression: Expression, flags: NodeCheckFlags, location: TextRange): LeftHandSideExpression {
|
||||
if (flags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
|
||||
return createPropertyAccess(
|
||||
return setTextRange(
|
||||
createCall(
|
||||
createIdentifier("_super"),
|
||||
/*typeArguments*/ undefined,
|
||||
[argumentExpression]
|
||||
),
|
||||
"value",
|
||||
location
|
||||
);
|
||||
}
|
||||
else {
|
||||
return createCall(
|
||||
createIdentifier("_super"),
|
||||
/*typeArguments*/ undefined,
|
||||
[argumentExpression],
|
||||
location
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getSuperContainerAsyncMethodFlags() {
|
||||
return currentSuperContainer !== undefined
|
||||
&& resolver.getNodeCheckFlags(currentSuperContainer) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
|
||||
}
|
||||
}
|
||||
|
||||
const awaiterHelper: EmitHelper = {
|
||||
name: "typescript:awaiter",
|
||||
scoped: false,
|
||||
priority: 5,
|
||||
text: `
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};`
|
||||
};
|
||||
|
||||
function createAwaiterHelper(context: TransformationContext, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
|
||||
context.requestEmitHelper(awaiterHelper);
|
||||
|
||||
const generatorFunc = createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
createToken(SyntaxKind.AsteriskToken),
|
||||
@@ -484,35 +483,22 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
const awaiterHelper: EmitHelper = {
|
||||
name: "typescript:awaiter",
|
||||
scoped: false,
|
||||
priority: 5,
|
||||
text: `
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};`
|
||||
};
|
||||
|
||||
const asyncSuperHelper: EmitHelper = {
|
||||
export const asyncSuperHelper: EmitHelper = {
|
||||
name: "typescript:async-super",
|
||||
scoped: true,
|
||||
text: `
|
||||
const _super = name => super[name];`
|
||||
const _super = name => super[name];
|
||||
`
|
||||
};
|
||||
|
||||
const advancedAsyncSuperHelper: EmitHelper = {
|
||||
export const advancedAsyncSuperHelper: EmitHelper = {
|
||||
name: "typescript:advanced-async-super",
|
||||
scoped: true,
|
||||
text: `
|
||||
const _super = (function (geti, seti) {
|
||||
const cache = Object.create(null);
|
||||
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
})(name => super[name], (name, value) => super[name] = value);`
|
||||
})(name => super[name], (name, value) => super[name] = value);
|
||||
`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ namespace ts {
|
||||
export function transformES5(context: TransformationContext) {
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
|
||||
// enable emit notification only if using --jsx preserve
|
||||
let previousOnEmitNode: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void;
|
||||
// enable emit notification only if using --jsx preserve or react-native
|
||||
let previousOnEmitNode: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
|
||||
let noSubstitution: boolean[];
|
||||
if (compilerOptions.jsx === JsxEmit.Preserve) {
|
||||
if (compilerOptions.jsx === JsxEmit.Preserve || compilerOptions.jsx === JsxEmit.ReactNative) {
|
||||
previousOnEmitNode = context.onEmitNode;
|
||||
context.onEmitNode = onEmitNode;
|
||||
context.enableEmitNotification(SyntaxKind.JsxOpeningElement);
|
||||
@@ -41,9 +41,11 @@ namespace ts {
|
||||
/**
|
||||
* Called by the printer just before a node is printed.
|
||||
*
|
||||
* @param node The node to be printed.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to emit.
|
||||
* @param emitCallback A callback used to emit the node.
|
||||
*/
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
|
||||
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (emitContext: EmitHint, node: Node) => void) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
case SyntaxKind.JsxClosingElement:
|
||||
@@ -53,21 +55,21 @@ namespace ts {
|
||||
break;
|
||||
}
|
||||
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param emitContext The context for the emitter.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to substitute.
|
||||
*/
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
function onSubstituteNode(hint: EmitHint, node: Node) {
|
||||
if (node.id && noSubstitution && noSubstitution[node.id]) {
|
||||
return previousOnSubstituteNode(emitContext, node);
|
||||
return previousOnSubstituteNode(hint, node);
|
||||
}
|
||||
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (isPropertyAccessExpression(node)) {
|
||||
return substitutePropertyAccessExpression(node);
|
||||
}
|
||||
@@ -85,7 +87,7 @@ namespace ts {
|
||||
function substitutePropertyAccessExpression(node: PropertyAccessExpression): Expression {
|
||||
const literalName = trySubstituteReservedName(node.name);
|
||||
if (literalName) {
|
||||
return createElementAccess(node.expression, literalName, /*location*/ node);
|
||||
return setTextRange(createElementAccess(node.expression, literalName), node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
@@ -111,9 +113,9 @@ namespace ts {
|
||||
function trySubstituteReservedName(name: Identifier) {
|
||||
const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(name.text) : undefined);
|
||||
if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) {
|
||||
return createLiteral(name, /*location*/ name);
|
||||
return setTextRange(createLiteral(name), name);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,35 @@
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../visitor.ts" />
|
||||
/// <reference path="es2017.ts" />
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
const enum ESNextSubstitutionFlags {
|
||||
/** Enables substitutions for async methods with `super` calls. */
|
||||
AsyncMethodsWithSuper = 1 << 0
|
||||
}
|
||||
|
||||
export function transformESNext(context: TransformationContext) {
|
||||
const {
|
||||
resumeLexicalEnvironment,
|
||||
endLexicalEnvironment
|
||||
endLexicalEnvironment,
|
||||
hoistVariableDeclaration
|
||||
} = context;
|
||||
|
||||
const resolver = context.getEmitResolver();
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
const languageVersion = getEmitScriptTarget(compilerOptions);
|
||||
|
||||
const previousOnEmitNode = context.onEmitNode;
|
||||
context.onEmitNode = onEmitNode;
|
||||
|
||||
const previousOnSubstituteNode = context.onSubstituteNode;
|
||||
context.onSubstituteNode = onSubstituteNode;
|
||||
|
||||
let enabledSubstitutions: ESNextSubstitutionFlags;
|
||||
let enclosingFunctionFlags: FunctionFlags;
|
||||
let enclosingSuperContainerFlags: NodeCheckFlags = 0;
|
||||
|
||||
return transformSourceFile;
|
||||
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
@@ -28,12 +50,25 @@ namespace ts {
|
||||
return visitorWorker(node, /*noDestructuringValue*/ true);
|
||||
}
|
||||
|
||||
function visitorNoAsyncModifier(node: Node): VisitResult<Node> {
|
||||
if (node.kind === SyntaxKind.AsyncKeyword) {
|
||||
return undefined;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function visitorWorker(node: Node, noDestructuringValue: boolean): VisitResult<Node> {
|
||||
if ((node.transformFlags & TransformFlags.ContainsESNext) === 0) {
|
||||
return node;
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.AwaitExpression:
|
||||
return visitAwaitExpression(node as AwaitExpression);
|
||||
case SyntaxKind.YieldExpression:
|
||||
return visitYieldExpression(node as YieldExpression);
|
||||
case SyntaxKind.LabeledStatement:
|
||||
return visitLabeledStatement(node as LabeledStatement);
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return visitObjectLiteralExpression(node as ObjectLiteralExpression);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
@@ -41,7 +76,7 @@ namespace ts {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return visitVariableDeclaration(node as VariableDeclaration);
|
||||
case SyntaxKind.ForOfStatement:
|
||||
return visitForOfStatement(node as ForOfStatement);
|
||||
return visitForOfStatement(node as ForOfStatement, /*outermostLabeledStatement*/ undefined);
|
||||
case SyntaxKind.ForStatement:
|
||||
return visitForStatement(node as ForStatement);
|
||||
case SyntaxKind.VoidExpression:
|
||||
@@ -71,6 +106,52 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function visitAwaitExpression(node: AwaitExpression) {
|
||||
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
return setOriginalNode(
|
||||
setTextRange(
|
||||
createYield(
|
||||
/*asteriskToken*/ undefined,
|
||||
createArrayLiteral([createLiteral("await"), expression])
|
||||
),
|
||||
/*location*/ node
|
||||
),
|
||||
node
|
||||
);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function visitYieldExpression(node: YieldExpression) {
|
||||
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
return updateYield(
|
||||
node,
|
||||
node.asteriskToken,
|
||||
node.asteriskToken
|
||||
? createAsyncDelegatorHelper(context, expression, expression)
|
||||
: createArrayLiteral(
|
||||
expression
|
||||
? [createLiteral("yield"), expression]
|
||||
: [createLiteral("yield")]
|
||||
)
|
||||
);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function visitLabeledStatement(node: LabeledStatement) {
|
||||
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
|
||||
const statement = unwrapInnermostStatementOfLabel(node);
|
||||
if (statement.kind === SyntaxKind.ForOfStatement && (<ForOfStatement>statement).awaitModifier) {
|
||||
return visitForOfStatement(<ForOfStatement>statement, node);
|
||||
}
|
||||
return restoreEnclosingLabel(visitEachChild(node, visitor, context), node);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function chunkObjectLiteralElements(elements: ObjectLiteralElement[]): Expression[] {
|
||||
let chunkObject: (ShorthandPropertyAssignment | PropertyAssignment)[];
|
||||
const objects: Expression[] = [];
|
||||
@@ -189,63 +270,199 @@ namespace ts {
|
||||
*
|
||||
* @param node A ForOfStatement.
|
||||
*/
|
||||
function visitForOfStatement(node: ForOfStatement): VisitResult<Statement> {
|
||||
let leadingStatements: Statement[];
|
||||
let temp: Identifier;
|
||||
const initializer = skipParentheses(node.initializer);
|
||||
if (initializer.transformFlags & TransformFlags.ContainsObjectRest) {
|
||||
if (isVariableDeclarationList(initializer)) {
|
||||
temp = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
const firstDeclaration = firstOrUndefined(initializer.declarations);
|
||||
const declarations = flattenDestructuringBinding(
|
||||
firstDeclaration,
|
||||
visitor,
|
||||
context,
|
||||
FlattenLevel.ObjectRest,
|
||||
temp,
|
||||
/*doNotRecordTempVariablesInLine*/ false,
|
||||
/*skipInitializer*/ true,
|
||||
);
|
||||
if (some(declarations)) {
|
||||
const statement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
updateVariableDeclarationList(initializer, declarations),
|
||||
/*location*/ initializer
|
||||
);
|
||||
leadingStatements = append(leadingStatements, statement);
|
||||
}
|
||||
}
|
||||
else if (isAssignmentPattern(initializer)) {
|
||||
temp = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
const expression = flattenDestructuringAssignment(
|
||||
aggregateTransformFlags(createAssignment(initializer, temp, /*location*/ node.initializer)),
|
||||
visitor,
|
||||
context,
|
||||
FlattenLevel.ObjectRest
|
||||
);
|
||||
leadingStatements = append(leadingStatements, createStatement(expression, /*location*/ node.initializer));
|
||||
}
|
||||
function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement): VisitResult<Statement> {
|
||||
if (node.initializer.transformFlags & TransformFlags.ContainsObjectRest) {
|
||||
node = transformForOfStatementWithObjectRest(node);
|
||||
}
|
||||
if (temp) {
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
const statement = visitNode(node.statement, visitor, isStatement);
|
||||
const block = isBlock(statement)
|
||||
? updateBlock(statement, createNodeArray(concatenate(leadingStatements, statement.statements), statement.statements))
|
||||
: createBlock(append(leadingStatements, statement), statement, /*multiLine*/ true);
|
||||
if (node.awaitModifier) {
|
||||
return transformForAwaitOfStatement(node, outermostLabeledStatement);
|
||||
}
|
||||
else {
|
||||
return restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement);
|
||||
}
|
||||
}
|
||||
|
||||
function transformForOfStatementWithObjectRest(node: ForOfStatement) {
|
||||
const initializerWithoutParens = skipParentheses(node.initializer) as ForInitializer;
|
||||
if (isVariableDeclarationList(initializerWithoutParens) || isAssignmentPattern(initializerWithoutParens)) {
|
||||
let bodyLocation: TextRange;
|
||||
let statementsLocation: TextRange;
|
||||
const temp = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
const statements: Statement[] = [createForOfBindingStatement(initializerWithoutParens, temp)];
|
||||
if (isBlock(node.statement)) {
|
||||
addRange(statements, node.statement.statements);
|
||||
bodyLocation = node.statement;
|
||||
statementsLocation = node.statement.statements;
|
||||
}
|
||||
return updateForOf(
|
||||
node,
|
||||
createVariableDeclarationList(
|
||||
[
|
||||
createVariableDeclaration(temp, /*type*/ undefined, /*initializer*/ undefined, node.initializer)
|
||||
],
|
||||
node.initializer,
|
||||
NodeFlags.Let
|
||||
node.awaitModifier,
|
||||
setTextRange(
|
||||
createVariableDeclarationList(
|
||||
[
|
||||
setTextRange(createVariableDeclaration(temp), node.initializer)
|
||||
],
|
||||
NodeFlags.Let
|
||||
),
|
||||
node.initializer
|
||||
),
|
||||
expression,
|
||||
block
|
||||
node.expression,
|
||||
setTextRange(
|
||||
createBlock(
|
||||
setTextRange(createNodeArray(statements), statementsLocation),
|
||||
/*multiLine*/ true
|
||||
),
|
||||
bodyLocation
|
||||
)
|
||||
);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
return node;
|
||||
}
|
||||
|
||||
function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression) {
|
||||
const binding = createForOfBindingStatement(node.initializer, boundValue);
|
||||
|
||||
let bodyLocation: TextRange;
|
||||
let statementsLocation: TextRange;
|
||||
const statements: Statement[] = [visitNode(binding, visitor, isStatement)];
|
||||
const statement = visitNode(node.statement, visitor, isStatement);
|
||||
if (isBlock(statement)) {
|
||||
addRange(statements, statement.statements);
|
||||
bodyLocation = statement;
|
||||
statementsLocation = statement.statements;
|
||||
}
|
||||
else {
|
||||
statements.push(statement);
|
||||
}
|
||||
|
||||
return setEmitFlags(
|
||||
setTextRange(
|
||||
createBlock(
|
||||
setTextRange(createNodeArray(statements), statementsLocation),
|
||||
/*multiLine*/ true
|
||||
),
|
||||
bodyLocation
|
||||
),
|
||||
EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps
|
||||
);
|
||||
}
|
||||
|
||||
function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement) {
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
const iterator = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined);
|
||||
const result = isIdentifier(expression) ? getGeneratedNameForNode(iterator) : createTempVariable(/*recordTempVariable*/ undefined);
|
||||
const errorRecord = createUniqueName("e");
|
||||
const catchVariable = getGeneratedNameForNode(errorRecord);
|
||||
const returnMethod = createTempVariable(/*recordTempVariable*/ undefined);
|
||||
const values = createAsyncValuesHelper(context, expression, /*location*/ node.expression);
|
||||
const next = createYield(
|
||||
/*asteriskToken*/ undefined,
|
||||
enclosingFunctionFlags & FunctionFlags.Generator
|
||||
? createArrayLiteral([
|
||||
createLiteral("await"),
|
||||
createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, [])
|
||||
])
|
||||
: createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, [])
|
||||
);
|
||||
|
||||
hoistVariableDeclaration(errorRecord);
|
||||
hoistVariableDeclaration(returnMethod);
|
||||
|
||||
const forStatement = setEmitFlags(
|
||||
setTextRange(
|
||||
createFor(
|
||||
/*initializer*/ setEmitFlags(
|
||||
setTextRange(
|
||||
createVariableDeclarationList([
|
||||
setTextRange(createVariableDeclaration(iterator, /*type*/ undefined, values), node.expression),
|
||||
createVariableDeclaration(result, /*type*/ undefined, next)
|
||||
]),
|
||||
node.expression
|
||||
),
|
||||
EmitFlags.NoHoisting
|
||||
),
|
||||
/*condition*/ createLogicalNot(createPropertyAccess(result, "done")),
|
||||
/*incrementor*/ createAssignment(result, next),
|
||||
/*statement*/ convertForOfStatementHead(node, createPropertyAccess(result, "value"))
|
||||
),
|
||||
/*location*/ node
|
||||
),
|
||||
EmitFlags.NoTokenTrailingSourceMaps
|
||||
);
|
||||
|
||||
return createTry(
|
||||
createBlock([
|
||||
restoreEnclosingLabel(
|
||||
forStatement,
|
||||
outermostLabeledStatement
|
||||
)
|
||||
]),
|
||||
createCatchClause(
|
||||
createVariableDeclaration(catchVariable),
|
||||
setEmitFlags(
|
||||
createBlock([
|
||||
createStatement(
|
||||
createAssignment(
|
||||
errorRecord,
|
||||
createObjectLiteral([
|
||||
createPropertyAssignment("error", catchVariable)
|
||||
])
|
||||
)
|
||||
)
|
||||
]),
|
||||
EmitFlags.SingleLine
|
||||
)
|
||||
),
|
||||
createBlock([
|
||||
createTry(
|
||||
/*tryBlock*/ createBlock([
|
||||
setEmitFlags(
|
||||
createIf(
|
||||
createLogicalAnd(
|
||||
createLogicalAnd(
|
||||
result,
|
||||
createLogicalNot(
|
||||
createPropertyAccess(result, "done")
|
||||
)
|
||||
),
|
||||
createAssignment(
|
||||
returnMethod,
|
||||
createPropertyAccess(iterator, "return")
|
||||
)
|
||||
),
|
||||
createStatement(
|
||||
createYield(
|
||||
/*asteriskToken*/ undefined,
|
||||
enclosingFunctionFlags & FunctionFlags.Generator
|
||||
? createArrayLiteral([
|
||||
createLiteral("await"),
|
||||
createFunctionCall(returnMethod, iterator, [])
|
||||
])
|
||||
: createFunctionCall(returnMethod, iterator, [])
|
||||
)
|
||||
)
|
||||
),
|
||||
EmitFlags.SingleLine
|
||||
)
|
||||
]),
|
||||
/*catchClause*/ undefined,
|
||||
/*finallyBlock*/ setEmitFlags(
|
||||
createBlock([
|
||||
setEmitFlags(
|
||||
createIf(
|
||||
errorRecord,
|
||||
createThrow(
|
||||
createPropertyAccess(errorRecord, "error")
|
||||
)
|
||||
),
|
||||
EmitFlags.SingleLine
|
||||
)
|
||||
]),
|
||||
EmitFlags.SingleLine
|
||||
)
|
||||
)
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
function visitParameter(node: ParameterDeclaration): ParameterDeclaration {
|
||||
@@ -258,6 +475,7 @@ namespace ts {
|
||||
/*modifiers*/ undefined,
|
||||
node.dotDotDotToken,
|
||||
getGeneratedNameForNode(node),
|
||||
/*questionToken*/ undefined,
|
||||
/*type*/ undefined,
|
||||
visitNode(node.initializer, visitor, isExpression)
|
||||
);
|
||||
@@ -266,17 +484,23 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitConstructorDeclaration(node: ConstructorDeclaration) {
|
||||
return updateConstructor(
|
||||
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
|
||||
enclosingFunctionFlags = FunctionFlags.Normal;
|
||||
const updated = updateConstructor(
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
node.modifiers,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
transformFunctionBody(node)
|
||||
);
|
||||
enclosingFunctionFlags = savedEnclosingFunctionFlags;
|
||||
return updated;
|
||||
}
|
||||
|
||||
function visitGetAccessorDeclaration(node: GetAccessorDeclaration) {
|
||||
return updateGetAccessor(
|
||||
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
|
||||
enclosingFunctionFlags = FunctionFlags.Normal;
|
||||
const updated = updateGetAccessor(
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
node.modifiers,
|
||||
@@ -285,10 +509,14 @@ namespace ts {
|
||||
/*type*/ undefined,
|
||||
transformFunctionBody(node)
|
||||
);
|
||||
enclosingFunctionFlags = savedEnclosingFunctionFlags;
|
||||
return updated;
|
||||
}
|
||||
|
||||
function visitSetAccessorDeclaration(node: SetAccessorDeclaration) {
|
||||
return updateSetAccessor(
|
||||
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
|
||||
enclosingFunctionFlags = FunctionFlags.Normal;
|
||||
const updated = updateSetAccessor(
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
node.modifiers,
|
||||
@@ -296,36 +524,63 @@ namespace ts {
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
transformFunctionBody(node)
|
||||
);
|
||||
enclosingFunctionFlags = savedEnclosingFunctionFlags;
|
||||
return updated;
|
||||
}
|
||||
|
||||
function visitMethodDeclaration(node: MethodDeclaration) {
|
||||
return updateMethod(
|
||||
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
|
||||
enclosingFunctionFlags = getFunctionFlags(node);
|
||||
const updated = updateMethod(
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
node.modifiers,
|
||||
enclosingFunctionFlags & FunctionFlags.Generator
|
||||
? visitNodes(node.modifiers, visitorNoAsyncModifier, isModifier)
|
||||
: node.modifiers,
|
||||
enclosingFunctionFlags & FunctionFlags.Async
|
||||
? undefined
|
||||
: node.asteriskToken,
|
||||
visitNode(node.name, visitor, isPropertyName),
|
||||
visitNode(/*questionToken*/ undefined, visitor, isToken),
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
transformFunctionBody(node)
|
||||
enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator
|
||||
? transformAsyncGeneratorFunctionBody(node)
|
||||
: transformFunctionBody(node)
|
||||
);
|
||||
enclosingFunctionFlags = savedEnclosingFunctionFlags;
|
||||
return updated;
|
||||
}
|
||||
|
||||
function visitFunctionDeclaration(node: FunctionDeclaration) {
|
||||
return updateFunctionDeclaration(
|
||||
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
|
||||
enclosingFunctionFlags = getFunctionFlags(node);
|
||||
const updated = updateFunctionDeclaration(
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
node.modifiers,
|
||||
enclosingFunctionFlags & FunctionFlags.Generator
|
||||
? visitNodes(node.modifiers, visitorNoAsyncModifier, isModifier)
|
||||
: node.modifiers,
|
||||
enclosingFunctionFlags & FunctionFlags.Async
|
||||
? undefined
|
||||
: node.asteriskToken,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
transformFunctionBody(node)
|
||||
enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator
|
||||
? transformAsyncGeneratorFunctionBody(node)
|
||||
: transformFunctionBody(node)
|
||||
);
|
||||
enclosingFunctionFlags = savedEnclosingFunctionFlags;
|
||||
return updated;
|
||||
}
|
||||
|
||||
function visitArrowFunction(node: ArrowFunction) {
|
||||
return updateArrowFunction(
|
||||
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
|
||||
enclosingFunctionFlags = getFunctionFlags(node);
|
||||
const updated = updateArrowFunction(
|
||||
node,
|
||||
node.modifiers,
|
||||
/*typeParameters*/ undefined,
|
||||
@@ -333,25 +588,99 @@ namespace ts {
|
||||
/*type*/ undefined,
|
||||
transformFunctionBody(node)
|
||||
);
|
||||
enclosingFunctionFlags = savedEnclosingFunctionFlags;
|
||||
return updated;
|
||||
}
|
||||
|
||||
function visitFunctionExpression(node: FunctionExpression) {
|
||||
return updateFunctionExpression(
|
||||
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
|
||||
enclosingFunctionFlags = getFunctionFlags(node);
|
||||
const updated = updateFunctionExpression(
|
||||
node,
|
||||
node.modifiers,
|
||||
enclosingFunctionFlags & FunctionFlags.Generator
|
||||
? visitNodes(node.modifiers, visitorNoAsyncModifier, isModifier)
|
||||
: node.modifiers,
|
||||
enclosingFunctionFlags & FunctionFlags.Async
|
||||
? undefined
|
||||
: node.asteriskToken,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
transformFunctionBody(node)
|
||||
enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator
|
||||
? transformAsyncGeneratorFunctionBody(node)
|
||||
: transformFunctionBody(node)
|
||||
);
|
||||
enclosingFunctionFlags = savedEnclosingFunctionFlags;
|
||||
return updated;
|
||||
}
|
||||
|
||||
function transformAsyncGeneratorFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody {
|
||||
resumeLexicalEnvironment();
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologue(statements, node.body.statements, /*ensureUseStrict*/ false, visitor);
|
||||
appendObjectRestAssignmentsIfNeeded(statements, node);
|
||||
|
||||
statements.push(
|
||||
createReturn(
|
||||
createAsyncGeneratorHelper(
|
||||
context,
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
createToken(SyntaxKind.AsteriskToken),
|
||||
node.name && getGeneratedNameForNode(node.name),
|
||||
/*typeParameters*/ undefined,
|
||||
/*parameters*/ [],
|
||||
/*type*/ undefined,
|
||||
updateBlock(
|
||||
node.body,
|
||||
visitLexicalEnvironment(node.body.statements, visitor, context, statementOffset)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
const block = updateBlock(node.body, statements);
|
||||
|
||||
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
|
||||
// This step isn't needed if we eventually transform this to ES5.
|
||||
if (languageVersion >= ScriptTarget.ES2015) {
|
||||
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
|
||||
enableSubstitutionForAsyncMethodsWithSuper();
|
||||
addEmitHelper(block, advancedAsyncSuperHelper);
|
||||
}
|
||||
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) {
|
||||
enableSubstitutionForAsyncMethodsWithSuper();
|
||||
addEmitHelper(block, asyncSuperHelper);
|
||||
}
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
function transformFunctionBody(node: FunctionDeclaration | FunctionExpression | ConstructorDeclaration | MethodDeclaration | AccessorDeclaration): FunctionBody;
|
||||
function transformFunctionBody(node: ArrowFunction): ConciseBody;
|
||||
function transformFunctionBody(node: FunctionLikeDeclaration): ConciseBody {
|
||||
resumeLexicalEnvironment();
|
||||
let leadingStatements: Statement[];
|
||||
let statementOffset = 0;
|
||||
const statements: Statement[] = [];
|
||||
const body = visitNode(node.body, visitor, isConciseBody);
|
||||
if (isBlock(body)) {
|
||||
statementOffset = addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor);
|
||||
}
|
||||
addRange(statements, appendObjectRestAssignmentsIfNeeded(/*statements*/ undefined, node));
|
||||
const trailingStatements = endLexicalEnvironment();
|
||||
if (statementOffset > 0 || some(statements) || some(trailingStatements)) {
|
||||
const block = convertToFunctionBody(body, /*multiLine*/ true);
|
||||
addRange(statements, block.statements.slice(statementOffset));
|
||||
addRange(statements, trailingStatements);
|
||||
return updateBlock(block, setTextRange(createNodeArray(statements), block.statements));
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
function appendObjectRestAssignmentsIfNeeded(statements: Statement[], node: FunctionLikeDeclaration): Statement[] {
|
||||
for (const parameter of node.parameters) {
|
||||
if (parameter.transformFlags & TransformFlags.ContainsObjectRest) {
|
||||
const temp = getGeneratedNameForNode(parameter);
|
||||
@@ -372,17 +701,153 @@ namespace ts {
|
||||
)
|
||||
);
|
||||
setEmitFlags(statement, EmitFlags.CustomPrologue);
|
||||
leadingStatements = append(leadingStatements, statement);
|
||||
statements = append(statements, statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
const body = visitNode(node.body, visitor, isConciseBody);
|
||||
const trailingStatements = endLexicalEnvironment();
|
||||
if (some(leadingStatements) || some(trailingStatements)) {
|
||||
const block = convertToFunctionBody(body, /*multiLine*/ true);
|
||||
return updateBlock(block, createNodeArray(concatenate(concatenate(leadingStatements, block.statements), trailingStatements), block.statements));
|
||||
return statements;
|
||||
}
|
||||
|
||||
function enableSubstitutionForAsyncMethodsWithSuper() {
|
||||
if ((enabledSubstitutions & ESNextSubstitutionFlags.AsyncMethodsWithSuper) === 0) {
|
||||
enabledSubstitutions |= ESNextSubstitutionFlags.AsyncMethodsWithSuper;
|
||||
|
||||
// We need to enable substitutions for call, property access, and element access
|
||||
// if we need to rewrite super calls.
|
||||
context.enableSubstitution(SyntaxKind.CallExpression);
|
||||
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
|
||||
context.enableSubstitution(SyntaxKind.ElementAccessExpression);
|
||||
|
||||
// We need to be notified when entering and exiting declarations that bind super.
|
||||
context.enableEmitNotification(SyntaxKind.ClassDeclaration);
|
||||
context.enableEmitNotification(SyntaxKind.MethodDeclaration);
|
||||
context.enableEmitNotification(SyntaxKind.GetAccessor);
|
||||
context.enableEmitNotification(SyntaxKind.SetAccessor);
|
||||
context.enableEmitNotification(SyntaxKind.Constructor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the printer just before a node is printed.
|
||||
*
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to be printed.
|
||||
* @param emitCallback The callback used to emit the node.
|
||||
*/
|
||||
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
|
||||
// If we need to support substitutions for `super` in an async method,
|
||||
// we should track it here.
|
||||
if (enabledSubstitutions & ESNextSubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
|
||||
const superContainerFlags = resolver.getNodeCheckFlags(node) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
|
||||
if (superContainerFlags !== enclosingSuperContainerFlags) {
|
||||
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
|
||||
enclosingSuperContainerFlags = superContainerFlags;
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
enclosingSuperContainerFlags = savedEnclosingSuperContainerFlags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param hint The context for the emitter.
|
||||
* @param node The node to substitute.
|
||||
*/
|
||||
function onSubstituteNode(hint: EmitHint, node: Node) {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (hint === EmitHint.Expression && enclosingSuperContainerFlags) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteExpression(node: Expression) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return substitutePropertyAccessExpression(<PropertyAccessExpression>node);
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
return substituteElementAccessExpression(<ElementAccessExpression>node);
|
||||
case SyntaxKind.CallExpression:
|
||||
return substituteCallExpression(<CallExpression>node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
createLiteral(node.name.text),
|
||||
node
|
||||
);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteElementAccessExpression(node: ElementAccessExpression) {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
return createSuperAccessInAsyncMethod(
|
||||
node.argumentExpression,
|
||||
node
|
||||
);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteCallExpression(node: CallExpression): Expression {
|
||||
const expression = node.expression;
|
||||
if (isSuperProperty(expression)) {
|
||||
const argumentExpression = isPropertyAccessExpression(expression)
|
||||
? substitutePropertyAccessExpression(expression)
|
||||
: substituteElementAccessExpression(expression);
|
||||
return createCall(
|
||||
createPropertyAccess(argumentExpression, "call"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
...node.arguments
|
||||
]
|
||||
);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function isSuperContainer(node: Node) {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ClassDeclaration
|
||||
|| kind === SyntaxKind.Constructor
|
||||
|| kind === SyntaxKind.MethodDeclaration
|
||||
|| kind === SyntaxKind.GetAccessor
|
||||
|| kind === SyntaxKind.SetAccessor;
|
||||
}
|
||||
|
||||
function createSuperAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
|
||||
if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
createCall(
|
||||
createIdentifier("_super"),
|
||||
/*typeArguments*/ undefined,
|
||||
[argumentExpression]
|
||||
),
|
||||
"value"
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
else {
|
||||
return setTextRange(
|
||||
createCall(
|
||||
createIdentifier("_super"),
|
||||
/*typeArguments*/ undefined,
|
||||
[argumentExpression]
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,6 +867,11 @@ namespace ts {
|
||||
};
|
||||
|
||||
export function createAssignHelper(context: TransformationContext, attributesSegments: Expression[]) {
|
||||
if (context.getCompilerOptions().target >= ScriptTarget.ES2015) {
|
||||
return createCall(createPropertyAccess(createIdentifier("Object"), "assign"),
|
||||
/*typeArguments*/ undefined,
|
||||
attributesSegments);
|
||||
}
|
||||
context.requestEmitHelper(assignHelper);
|
||||
return createCall(
|
||||
getHelperName("__assign"),
|
||||
@@ -409,4 +879,89 @@ namespace ts {
|
||||
attributesSegments
|
||||
);
|
||||
}
|
||||
|
||||
const asyncGeneratorHelper: EmitHelper = {
|
||||
name: "typescript:asyncGenerator",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
||||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||
var g = generator.apply(thisArg, _arguments || []), q = [], c, i;
|
||||
return i = { next: verb("next"), "throw": verb("throw"), "return": verb("return") }, i[Symbol.asyncIterator] = function () { return this; }, i;
|
||||
function verb(n) { return function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]), next(); }); }; }
|
||||
function next() { if (!c && q.length) resume((c = q.shift())[0], c[1]); }
|
||||
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(c[3], e); } }
|
||||
function step(r) { r.done ? settle(c[2], r) : r.value[0] === "yield" ? settle(c[2], { value: r.value[1], done: false }) : Promise.resolve(r.value[1]).then(r.value[0] === "delegate" ? delegate : fulfill, reject); }
|
||||
function delegate(r) { step(r.done ? r : { value: ["yield", r.value], done: false }); }
|
||||
function fulfill(value) { resume("next", value); }
|
||||
function reject(value) { resume("throw", value); }
|
||||
function settle(f, v) { c = void 0, f(v), next(); }
|
||||
};
|
||||
`
|
||||
};
|
||||
|
||||
function createAsyncGeneratorHelper(context: TransformationContext, generatorFunc: FunctionExpression) {
|
||||
context.requestEmitHelper(asyncGeneratorHelper);
|
||||
|
||||
// Mark this node as originally an async function
|
||||
(generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody;
|
||||
|
||||
return createCall(
|
||||
getHelperName("__asyncGenerator"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
createIdentifier("arguments"),
|
||||
generatorFunc
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
const asyncDelegator: EmitHelper = {
|
||||
name: "typescript:asyncDelegator",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
|
||||
var i = { next: verb("next"), "throw": verb("throw", function (e) { throw e; }), "return": verb("return", function (v) { return { value: v, done: true }; }) };
|
||||
return o = __asyncValues(o), i[Symbol.iterator] = function () { return this; }, i;
|
||||
function verb(n, f) { return function (v) { return { value: ["delegate", (o[n] || f).call(o, v)], done: false }; }; }
|
||||
};
|
||||
`
|
||||
};
|
||||
|
||||
function createAsyncDelegatorHelper(context: TransformationContext, expression: Expression, location?: TextRange) {
|
||||
context.requestEmitHelper(asyncDelegator);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__asyncDelegator"),
|
||||
/*typeArguments*/ undefined,
|
||||
[expression]
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
const asyncValues: EmitHelper = {
|
||||
name: "typescript:asyncValues",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __asyncValues = (this && this.__asyncIterator) || function (o) {
|
||||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||
var m = o[Symbol.asyncIterator];
|
||||
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
|
||||
};
|
||||
`
|
||||
};
|
||||
|
||||
function createAsyncValuesHelper(context: TransformationContext, expression: Expression, location?: TextRange) {
|
||||
context.requestEmitHelper(asyncValues);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__asyncValues"),
|
||||
/*typeArguments*/ undefined,
|
||||
[expression]
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../visitor.ts" />
|
||||
|
||||
// Transforms generator functions into a compatible ES5 representation with similar runtime
|
||||
@@ -232,7 +232,7 @@ namespace ts {
|
||||
resumeLexicalEnvironment,
|
||||
endLexicalEnvironment,
|
||||
hoistFunctionDeclaration,
|
||||
hoistVariableDeclaration,
|
||||
hoistVariableDeclaration
|
||||
} = context;
|
||||
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
@@ -448,17 +448,19 @@ namespace ts {
|
||||
*/
|
||||
function visitFunctionDeclaration(node: FunctionDeclaration): Statement {
|
||||
// Currently, we only support generators that were originally async functions.
|
||||
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
|
||||
if (node.asteriskToken) {
|
||||
node = setOriginalNode(
|
||||
createFunctionDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
node.modifiers,
|
||||
/*asteriskToken*/ undefined,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
transformGeneratorFunctionBody(node.body),
|
||||
setTextRange(
|
||||
createFunctionDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
node.modifiers,
|
||||
/*asteriskToken*/ undefined,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
transformGeneratorFunctionBody(node.body)
|
||||
),
|
||||
/*location*/ node
|
||||
),
|
||||
node
|
||||
@@ -496,16 +498,18 @@ namespace ts {
|
||||
*/
|
||||
function visitFunctionExpression(node: FunctionExpression): Expression {
|
||||
// Currently, we only support generators that were originally async functions.
|
||||
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
|
||||
if (node.asteriskToken) {
|
||||
node = setOriginalNode(
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
transformGeneratorFunctionBody(node.body),
|
||||
setTextRange(
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
transformGeneratorFunctionBody(node.body)
|
||||
),
|
||||
/*location*/ node
|
||||
),
|
||||
node
|
||||
@@ -583,7 +587,7 @@ namespace ts {
|
||||
// Build the generator
|
||||
resumeLexicalEnvironment();
|
||||
|
||||
const statementOffset = addPrologueDirectives(statements, body.statements, /*ensureUseStrict*/ false, visitor);
|
||||
const statementOffset = addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor);
|
||||
|
||||
transformAndEmitStatements(body.statements, statementOffset);
|
||||
|
||||
@@ -606,7 +610,7 @@ namespace ts {
|
||||
operationLocations = savedOperationLocations;
|
||||
state = savedState;
|
||||
|
||||
return createBlock(statements, /*location*/ body, body.multiLine);
|
||||
return setTextRange(createBlock(statements, body.multiLine), body);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -739,14 +743,17 @@ namespace ts {
|
||||
|
||||
const operator = node.operatorToken.kind;
|
||||
if (isCompoundAssignment(operator)) {
|
||||
return createBinary(
|
||||
target,
|
||||
SyntaxKind.EqualsToken,
|
||||
createBinary(
|
||||
cacheExpression(target),
|
||||
getOperatorForCompoundAssignment(operator),
|
||||
visitNode(right, visitor, isExpression),
|
||||
node
|
||||
return setTextRange(
|
||||
createAssignment(
|
||||
target,
|
||||
setTextRange(
|
||||
createBinary(
|
||||
cacheExpression(target),
|
||||
getOperatorForCompoundAssignment(operator),
|
||||
visitNode(right, visitor, isExpression)
|
||||
),
|
||||
node
|
||||
)
|
||||
),
|
||||
node
|
||||
);
|
||||
@@ -929,11 +936,13 @@ namespace ts {
|
||||
// .mark resumeLabel
|
||||
// x = %sent%;
|
||||
|
||||
// NOTE: we are explicitly not handling YieldStar at this time.
|
||||
const resumeLabel = defineLabel();
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
if (node.asteriskToken) {
|
||||
emitYieldStar(expression, /*location*/ node);
|
||||
const iterator = (getEmitFlags(node.expression) & EmitFlags.Iterator) === 0
|
||||
? createValuesHelper(context, expression, /*location*/ node)
|
||||
: expression;
|
||||
emitYieldStar(iterator, /*location*/ node);
|
||||
}
|
||||
else {
|
||||
emitYield(expression, /*location*/ node);
|
||||
@@ -971,9 +980,10 @@ namespace ts {
|
||||
// ar = _a.concat([%sent%, 2]);
|
||||
|
||||
const numInitialElements = countInitialNodesWithoutYield(elements);
|
||||
const temp = declareLocal();
|
||||
let hasAssignedTemp = false;
|
||||
|
||||
let temp: Identifier;
|
||||
if (numInitialElements > 0) {
|
||||
temp = declareLocal();
|
||||
const initialElements = visitNodes(elements, visitor, isExpression, 0, numInitialElements);
|
||||
emitAssignment(temp,
|
||||
createArrayLiteral(
|
||||
@@ -983,30 +993,35 @@ namespace ts {
|
||||
)
|
||||
);
|
||||
leadingElement = undefined;
|
||||
hasAssignedTemp = true;
|
||||
}
|
||||
|
||||
const expressions = reduceLeft(elements, reduceElement, <Expression[]>[], numInitialElements);
|
||||
return hasAssignedTemp
|
||||
? createArrayConcat(temp, [createArrayLiteral(expressions, /*location*/ undefined, multiLine)])
|
||||
: createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, location, multiLine);
|
||||
return temp
|
||||
? createArrayConcat(temp, [createArrayLiteral(expressions, multiLine)])
|
||||
: setTextRange(
|
||||
createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, multiLine),
|
||||
location
|
||||
);
|
||||
|
||||
function reduceElement(expressions: Expression[], element: Expression) {
|
||||
if (containsYield(element) && expressions.length > 0) {
|
||||
const hasAssignedTemp = temp !== undefined;
|
||||
if (!temp) {
|
||||
temp = declareLocal();
|
||||
}
|
||||
|
||||
emitAssignment(
|
||||
temp,
|
||||
hasAssignedTemp
|
||||
? createArrayConcat(
|
||||
temp,
|
||||
[createArrayLiteral(expressions, /*location*/ undefined, multiLine)]
|
||||
[createArrayLiteral(expressions, multiLine)]
|
||||
)
|
||||
: createArrayLiteral(
|
||||
leadingElement ? [leadingElement, ...expressions] : expressions,
|
||||
/*location*/ undefined,
|
||||
multiLine
|
||||
)
|
||||
);
|
||||
hasAssignedTemp = true;
|
||||
leadingElement = undefined;
|
||||
expressions = [];
|
||||
}
|
||||
@@ -1043,7 +1058,6 @@ namespace ts {
|
||||
emitAssignment(temp,
|
||||
createObjectLiteral(
|
||||
visitNodes(properties, visitor, isObjectLiteralElementLike, 0, numInitialProperties),
|
||||
/*location*/ undefined,
|
||||
multiLine
|
||||
)
|
||||
);
|
||||
@@ -1139,18 +1153,20 @@ namespace ts {
|
||||
|
||||
const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration);
|
||||
return setOriginalNode(
|
||||
createNew(
|
||||
createFunctionApply(
|
||||
cacheExpression(visitNode(target, visitor, isExpression)),
|
||||
thisArg,
|
||||
visitElements(
|
||||
node.arguments,
|
||||
/*leadingElement*/ createVoidZero()
|
||||
)
|
||||
setTextRange(
|
||||
createNew(
|
||||
createFunctionApply(
|
||||
cacheExpression(visitNode(target, visitor, isExpression)),
|
||||
thisArg,
|
||||
visitElements(
|
||||
node.arguments,
|
||||
/*leadingElement*/ createVoidZero()
|
||||
)
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
[]
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
[],
|
||||
/*location*/ node
|
||||
node
|
||||
),
|
||||
node
|
||||
);
|
||||
@@ -1217,7 +1233,7 @@ namespace ts {
|
||||
case SyntaxKind.TryStatement:
|
||||
return transformAndEmitTryStatement(<TryStatement>node);
|
||||
default:
|
||||
return emitStatement(visitNode(node, visitor, isStatement, /*optional*/ true));
|
||||
return emitStatement(visitNode(node, visitor, isStatement));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1423,9 +1439,11 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
emitStatement(
|
||||
createStatement(
|
||||
visitNode(initializer, visitor, isExpression),
|
||||
/*location*/ initializer
|
||||
setTextRange(
|
||||
createStatement(
|
||||
visitNode(initializer, visitor, isExpression)
|
||||
),
|
||||
initializer
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -1441,9 +1459,11 @@ namespace ts {
|
||||
markLabel(incrementLabel);
|
||||
if (node.incrementor) {
|
||||
emitStatement(
|
||||
createStatement(
|
||||
visitNode(node.incrementor, visitor, isExpression),
|
||||
/*location*/ node.incrementor
|
||||
setTextRange(
|
||||
createStatement(
|
||||
visitNode(node.incrementor, visitor, isExpression)
|
||||
),
|
||||
node.incrementor
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -1461,7 +1481,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const initializer = node.initializer;
|
||||
if (isVariableDeclarationList(initializer)) {
|
||||
if (initializer && isVariableDeclarationList(initializer)) {
|
||||
for (const variable of initializer.declarations) {
|
||||
hoistVariableDeclaration(<Identifier>variable.name);
|
||||
}
|
||||
@@ -1471,9 +1491,9 @@ namespace ts {
|
||||
variables.length > 0
|
||||
? inlineExpressions(map(variables, transformInitializedVariable))
|
||||
: undefined,
|
||||
visitNode(node.condition, visitor, isExpression, /*optional*/ true),
|
||||
visitNode(node.incrementor, visitor, isExpression, /*optional*/ true),
|
||||
visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock)
|
||||
visitNode(node.condition, visitor, isExpression),
|
||||
visitNode(node.incrementor, visitor, isExpression),
|
||||
visitNode(node.statement, visitor, isStatement, liftToBlock)
|
||||
);
|
||||
}
|
||||
else {
|
||||
@@ -1595,7 +1615,7 @@ namespace ts {
|
||||
node = updateForIn(node,
|
||||
<Identifier>initializer.declarations[0].name,
|
||||
visitNode(node.expression, visitor, isExpression),
|
||||
visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock)
|
||||
visitNode(node.statement, visitor, isStatement, liftToBlock)
|
||||
);
|
||||
}
|
||||
else {
|
||||
@@ -1645,14 +1665,14 @@ namespace ts {
|
||||
|
||||
function transformAndEmitReturnStatement(node: ReturnStatement): void {
|
||||
emitReturn(
|
||||
visitNode(node.expression, visitor, isExpression, /*optional*/ true),
|
||||
visitNode(node.expression, visitor, isExpression),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
|
||||
function visitReturnStatement(node: ReturnStatement) {
|
||||
return createInlineReturn(
|
||||
visitNode(node.expression, visitor, isExpression, /*optional*/ true),
|
||||
visitNode(node.expression, visitor, isExpression),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
@@ -1909,9 +1929,9 @@ namespace ts {
|
||||
return -1;
|
||||
}
|
||||
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node): Node {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
function onSubstituteNode(hint: EmitHint, node: Node): Node {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (hint === EmitHint.Expression) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
return node;
|
||||
@@ -1925,7 +1945,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function substituteExpressionIdentifier(node: Identifier) {
|
||||
if (renamedCatchVariables && renamedCatchVariables.has(node.text)) {
|
||||
if (!isGeneratedIdentifier(node) && renamedCatchVariables && renamedCatchVariables.has(node.text)) {
|
||||
const original = getOriginalNode(node);
|
||||
if (isIdentifier(original) && original.parent) {
|
||||
const declaration = resolver.getReferencedValueDeclaration(original);
|
||||
@@ -1946,7 +1966,7 @@ namespace ts {
|
||||
|
||||
function cacheExpression(node: Expression): Identifier {
|
||||
let temp: Identifier;
|
||||
if (isGeneratedIdentifier(node)) {
|
||||
if (isGeneratedIdentifier(node) || getEmitFlags(node) & EmitFlags.HelperName) {
|
||||
return <Identifier>node;
|
||||
}
|
||||
|
||||
@@ -2091,17 +2111,24 @@ namespace ts {
|
||||
function beginCatchBlock(variable: VariableDeclaration): void {
|
||||
Debug.assert(peekBlockKind() === CodeBlockKind.Exception);
|
||||
|
||||
const text = (<Identifier>variable.name).text;
|
||||
const name = declareLocal(text);
|
||||
|
||||
if (!renamedCatchVariables) {
|
||||
renamedCatchVariables = createMap<boolean>();
|
||||
renamedCatchVariableDeclarations = [];
|
||||
context.enableSubstitution(SyntaxKind.Identifier);
|
||||
// generated identifiers should already be unique within a file
|
||||
let name: Identifier;
|
||||
if (isGeneratedIdentifier(variable.name)) {
|
||||
name = variable.name;
|
||||
hoistVariableDeclaration(variable.name);
|
||||
}
|
||||
else {
|
||||
const text = (<Identifier>variable.name).text;
|
||||
name = declareLocal(text);
|
||||
if (!renamedCatchVariables) {
|
||||
renamedCatchVariables = createMap<boolean>();
|
||||
renamedCatchVariableDeclarations = [];
|
||||
context.enableSubstitution(SyntaxKind.Identifier);
|
||||
}
|
||||
|
||||
renamedCatchVariables.set(text, true);
|
||||
renamedCatchVariableDeclarations[getOriginalNodeId(variable)] = name;
|
||||
renamedCatchVariables.set(text, true);
|
||||
renamedCatchVariableDeclarations[getOriginalNodeId(variable)] = name;
|
||||
}
|
||||
|
||||
const exception = <ExceptionBlock>peekBlock();
|
||||
Debug.assert(exception.state < ExceptionBlockState.Catch);
|
||||
@@ -2405,7 +2432,7 @@ namespace ts {
|
||||
*/
|
||||
function createInstruction(instruction: Instruction): NumericLiteral {
|
||||
const literal = createLiteral(instruction);
|
||||
literal.trailingComment = getInstructionName(instruction);
|
||||
addSyntheticTrailingComment(literal, SyntaxKind.MultiLineCommentTrivia, getInstructionName(instruction));
|
||||
return literal;
|
||||
}
|
||||
|
||||
@@ -2417,11 +2444,13 @@ namespace ts {
|
||||
*/
|
||||
function createInlineBreak(label: Label, location?: TextRange): ReturnStatement {
|
||||
Debug.assert(label > 0, `Invalid label: ${label}`);
|
||||
return createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.Break),
|
||||
createLabel(label)
|
||||
]),
|
||||
return setTextRange(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.Break),
|
||||
createLabel(label)
|
||||
])
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
@@ -2433,10 +2462,12 @@ namespace ts {
|
||||
* @param location An optional source map location for the statement.
|
||||
*/
|
||||
function createInlineReturn(expression?: Expression, location?: TextRange): ReturnStatement {
|
||||
return createReturn(
|
||||
createArrayLiteral(expression
|
||||
? [createInstruction(Instruction.Return), expression]
|
||||
: [createInstruction(Instruction.Return)]
|
||||
return setTextRange(
|
||||
createReturn(
|
||||
createArrayLiteral(expression
|
||||
? [createInstruction(Instruction.Return), expression]
|
||||
: [createInstruction(Instruction.Return)]
|
||||
)
|
||||
),
|
||||
location
|
||||
);
|
||||
@@ -2446,7 +2477,14 @@ namespace ts {
|
||||
* Creates an expression that can be used to resume from a Yield operation.
|
||||
*/
|
||||
function createGeneratorResume(location?: TextRange): LeftHandSideExpression {
|
||||
return createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [], location);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
createPropertyAccess(state, "sent"),
|
||||
/*typeArguments*/ undefined,
|
||||
[]
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2614,7 +2652,6 @@ namespace ts {
|
||||
/*type*/ undefined,
|
||||
createBlock(
|
||||
buildResult,
|
||||
/*location*/ undefined,
|
||||
/*multiLine*/ buildResult.length > 0
|
||||
)
|
||||
),
|
||||
@@ -2944,7 +2981,7 @@ namespace ts {
|
||||
* @param operationLocation The source map location for the operation.
|
||||
*/
|
||||
function writeAssign(left: Expression, right: Expression, operationLocation: TextRange): void {
|
||||
writeStatement(createStatement(createAssignment(left, right), operationLocation));
|
||||
writeStatement(setTextRange(createStatement(createAssignment(left, right)), operationLocation));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2956,7 +2993,7 @@ namespace ts {
|
||||
function writeThrow(expression: Expression, operationLocation: TextRange): void {
|
||||
lastOperationWasAbrupt = true;
|
||||
lastOperationWasCompletion = true;
|
||||
writeStatement(createThrow(expression, operationLocation));
|
||||
writeStatement(setTextRange(createThrow(expression), operationLocation));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2970,10 +3007,12 @@ namespace ts {
|
||||
lastOperationWasCompletion = true;
|
||||
writeStatement(
|
||||
setEmitFlags(
|
||||
createReturn(
|
||||
createArrayLiteral(expression
|
||||
? [createInstruction(Instruction.Return), expression]
|
||||
: [createInstruction(Instruction.Return)]
|
||||
setTextRange(
|
||||
createReturn(
|
||||
createArrayLiteral(expression
|
||||
? [createInstruction(Instruction.Return), expression]
|
||||
: [createInstruction(Instruction.Return)]
|
||||
)
|
||||
),
|
||||
operationLocation
|
||||
),
|
||||
@@ -2992,11 +3031,13 @@ namespace ts {
|
||||
lastOperationWasAbrupt = true;
|
||||
writeStatement(
|
||||
setEmitFlags(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.Break),
|
||||
createLabel(label)
|
||||
]),
|
||||
setTextRange(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.Break),
|
||||
createLabel(label)
|
||||
])
|
||||
),
|
||||
operationLocation
|
||||
),
|
||||
EmitFlags.NoTokenSourceMaps
|
||||
@@ -3017,11 +3058,13 @@ namespace ts {
|
||||
createIf(
|
||||
condition,
|
||||
setEmitFlags(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.Break),
|
||||
createLabel(label)
|
||||
]),
|
||||
setTextRange(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.Break),
|
||||
createLabel(label)
|
||||
])
|
||||
),
|
||||
operationLocation
|
||||
),
|
||||
EmitFlags.NoTokenSourceMaps
|
||||
@@ -3045,11 +3088,13 @@ namespace ts {
|
||||
createIf(
|
||||
createLogicalNot(condition),
|
||||
setEmitFlags(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.Break),
|
||||
createLabel(label)
|
||||
]),
|
||||
setTextRange(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.Break),
|
||||
createLabel(label)
|
||||
])
|
||||
),
|
||||
operationLocation
|
||||
),
|
||||
EmitFlags.NoTokenSourceMaps
|
||||
@@ -3070,11 +3115,13 @@ namespace ts {
|
||||
lastOperationWasAbrupt = true;
|
||||
writeStatement(
|
||||
setEmitFlags(
|
||||
createReturn(
|
||||
createArrayLiteral(
|
||||
expression
|
||||
? [createInstruction(Instruction.Yield), expression]
|
||||
: [createInstruction(Instruction.Yield)]
|
||||
setTextRange(
|
||||
createReturn(
|
||||
createArrayLiteral(
|
||||
expression
|
||||
? [createInstruction(Instruction.Yield), expression]
|
||||
: [createInstruction(Instruction.Yield)]
|
||||
)
|
||||
),
|
||||
operationLocation
|
||||
),
|
||||
@@ -3093,11 +3140,13 @@ namespace ts {
|
||||
lastOperationWasAbrupt = true;
|
||||
writeStatement(
|
||||
setEmitFlags(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.YieldStar),
|
||||
expression
|
||||
]),
|
||||
setTextRange(
|
||||
createReturn(
|
||||
createArrayLiteral([
|
||||
createInstruction(Instruction.YieldStar),
|
||||
expression
|
||||
])
|
||||
),
|
||||
operationLocation
|
||||
),
|
||||
EmitFlags.NoTokenSourceMaps
|
||||
@@ -3193,8 +3242,8 @@ namespace ts {
|
||||
priority: 6,
|
||||
text: `
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;
|
||||
return { next: verb(0), "throw": verb(1), "return": verb(2) };
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
namespace ts {
|
||||
export function transformJsx(context: TransformationContext) {
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
let currentSourceFile: SourceFile;
|
||||
|
||||
return transformSourceFile;
|
||||
|
||||
@@ -20,12 +19,8 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
currentSourceFile = node;
|
||||
|
||||
const visited = visitEachChild(node, visitor, context);
|
||||
addEmitHelpers(visited, context.readEmitHelpers());
|
||||
|
||||
currentSourceFile = undefined;
|
||||
return visited;
|
||||
}
|
||||
|
||||
@@ -85,7 +80,7 @@ namespace ts {
|
||||
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[], isChild: boolean, location: TextRange) {
|
||||
const tagName = getTagName(node);
|
||||
let objectProperties: Expression;
|
||||
const attrs = node.attributes;
|
||||
const attrs = node.attributes.properties;
|
||||
if (attrs.length === 0) {
|
||||
// When there are no attributes, React wants "null"
|
||||
objectProperties = createNull();
|
||||
@@ -143,15 +138,15 @@ namespace ts {
|
||||
|
||||
function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression) {
|
||||
if (node === undefined) {
|
||||
return createLiteral(true);
|
||||
return createTrue();
|
||||
}
|
||||
else if (node.kind === SyntaxKind.StringLiteral) {
|
||||
const decoded = tryDecodeEntities((<StringLiteral>node).text);
|
||||
return decoded ? createLiteral(decoded, /*location*/ node) : node;
|
||||
return decoded ? setTextRange(createLiteral(decoded), node) : node;
|
||||
}
|
||||
else if (node.kind === SyntaxKind.JsxExpression) {
|
||||
if (node.expression === undefined) {
|
||||
return createLiteral(true);
|
||||
return createTrue();
|
||||
}
|
||||
return visitJsxExpression(<JsxExpression>node);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace ts {
|
||||
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(node, compilerOptions);
|
||||
if (externalHelpersModuleName) {
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements);
|
||||
const statementOffset = addPrologue(statements, node.statements);
|
||||
append(statements,
|
||||
createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
@@ -37,7 +37,7 @@ namespace ts {
|
||||
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
|
||||
return updateSourceFileNode(
|
||||
node,
|
||||
createNodeArray(statements, node.statements));
|
||||
setTextRange(createNodeArray(statements), node.statements));
|
||||
}
|
||||
else {
|
||||
return visitEachChild(node, visitor, context);
|
||||
@@ -71,18 +71,18 @@ namespace ts {
|
||||
/**
|
||||
* Hook for node emit.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to emit.
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
*/
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
|
||||
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
|
||||
if (isSourceFile(node)) {
|
||||
currentSourceFile = node;
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
currentSourceFile = undefined;
|
||||
}
|
||||
else {
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,14 +93,15 @@ namespace ts {
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to substitute.
|
||||
*/
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
if (isIdentifier(node) && emitContext === EmitContext.Expression) {
|
||||
function onSubstituteNode(hint: EmitHint, node: Node) {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (isIdentifier(node) && hint === EmitHint.Expression) {
|
||||
return substituteExpressionIdentifier(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../visitor.ts" />
|
||||
/// <reference path="../destructuring.ts" />
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
@@ -54,9 +55,7 @@ namespace ts {
|
||||
* @param node The SourceFile node.
|
||||
*/
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
if (isDeclarationFile(node)
|
||||
|| !(isExternalModule(node)
|
||||
|| compilerOptions.isolatedModules)) {
|
||||
if (isDeclarationFile(node) || !(isExternalModule(node) || compilerOptions.isolatedModules)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -73,6 +72,14 @@ namespace ts {
|
||||
return aggregateTransformFlags(updated);
|
||||
}
|
||||
|
||||
|
||||
function shouldEmitUnderscoreUnderscoreESModule() {
|
||||
if (!currentModuleInfo.exportEquals && isExternalModule(currentSourceFile)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a SourceFile into a CommonJS module.
|
||||
*
|
||||
@@ -82,17 +89,24 @@ namespace ts {
|
||||
startLexicalEnvironment();
|
||||
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
|
||||
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
|
||||
const ensureUseStrict = compilerOptions.alwaysStrict || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile));
|
||||
const statementOffset = addPrologue(statements, node.statements, ensureUseStrict, sourceElementVisitor);
|
||||
|
||||
const updated = updateSourceFileNode(node, createNodeArray(statements, node.statements));
|
||||
if (currentModuleInfo.hasExportStarsToExportValues) {
|
||||
addEmitHelper(updated, exportStarHelper);
|
||||
if (shouldEmitUnderscoreUnderscoreESModule()) {
|
||||
append(statements, createUnderscoreUnderscoreESModule());
|
||||
}
|
||||
|
||||
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement));
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
|
||||
const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements));
|
||||
if (currentModuleInfo.hasExportStarsToExportValues) {
|
||||
// If we have any `export * from ...` declarations
|
||||
// we need to inform the emitter to add the __export helper.
|
||||
addEmitHelper(updated, exportStarHelper);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@@ -131,47 +145,49 @@ namespace ts {
|
||||
// Create an updated SourceFile:
|
||||
//
|
||||
// define(moduleName?, ["module1", "module2"], function ...
|
||||
return updateSourceFileNode(node, createNodeArray(
|
||||
[
|
||||
createStatement(
|
||||
createCall(
|
||||
define,
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
// Add the module name (if provided).
|
||||
...(moduleName ? [moduleName] : []),
|
||||
return updateSourceFileNode(node,
|
||||
setTextRange(
|
||||
createNodeArray([
|
||||
createStatement(
|
||||
createCall(
|
||||
define,
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
// Add the module name (if provided).
|
||||
...(moduleName ? [moduleName] : []),
|
||||
|
||||
// Add the dependency array argument:
|
||||
//
|
||||
// ["require", "exports", module1", "module2", ...]
|
||||
createArrayLiteral([
|
||||
createLiteral("require"),
|
||||
createLiteral("exports"),
|
||||
...aliasedModuleNames,
|
||||
...unaliasedModuleNames
|
||||
]),
|
||||
// Add the dependency array argument:
|
||||
//
|
||||
// ["require", "exports", module1", "module2", ...]
|
||||
createArrayLiteral([
|
||||
createLiteral("require"),
|
||||
createLiteral("exports"),
|
||||
...aliasedModuleNames,
|
||||
...unaliasedModuleNames
|
||||
]),
|
||||
|
||||
// Add the module body function argument:
|
||||
//
|
||||
// function (require, exports, module1, module2) ...
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"),
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"),
|
||||
...importAliasNames
|
||||
],
|
||||
/*type*/ undefined,
|
||||
transformAsynchronousModuleBody(node)
|
||||
)
|
||||
]
|
||||
// Add the module body function argument:
|
||||
//
|
||||
// function (require, exports, module1, module2) ...
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"),
|
||||
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"),
|
||||
...importAliasNames
|
||||
],
|
||||
/*type*/ undefined,
|
||||
transformAsynchronousModuleBody(node)
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
/*location*/ node.statements)
|
||||
]),
|
||||
/*location*/ node.statements
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -189,74 +205,76 @@ namespace ts {
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "factory")],
|
||||
/*type*/ undefined,
|
||||
createBlock(
|
||||
[
|
||||
createIf(
|
||||
createLogicalAnd(
|
||||
createTypeCheck(createIdentifier("module"), "object"),
|
||||
createTypeCheck(createPropertyAccess(createIdentifier("module"), "exports"), "object")
|
||||
),
|
||||
createBlock([
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
[
|
||||
createVariableDeclaration(
|
||||
"v",
|
||||
/*type*/ undefined,
|
||||
setTextRange(
|
||||
createBlock(
|
||||
[
|
||||
createIf(
|
||||
createLogicalAnd(
|
||||
createTypeCheck(createIdentifier("module"), "object"),
|
||||
createTypeCheck(createPropertyAccess(createIdentifier("module"), "exports"), "object")
|
||||
),
|
||||
createBlock([
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
[
|
||||
createVariableDeclaration(
|
||||
"v",
|
||||
/*type*/ undefined,
|
||||
createCall(
|
||||
createIdentifier("factory"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createIdentifier("require"),
|
||||
createIdentifier("exports")
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
),
|
||||
setEmitFlags(
|
||||
createIf(
|
||||
createStrictInequality(
|
||||
createIdentifier("v"),
|
||||
createIdentifier("undefined")
|
||||
),
|
||||
createStatement(
|
||||
createAssignment(
|
||||
createPropertyAccess(createIdentifier("module"), "exports"),
|
||||
createIdentifier("v")
|
||||
)
|
||||
)
|
||||
),
|
||||
EmitFlags.SingleLine
|
||||
)
|
||||
]),
|
||||
createIf(
|
||||
createLogicalAnd(
|
||||
createTypeCheck(createIdentifier("define"), "function"),
|
||||
createPropertyAccess(createIdentifier("define"), "amd")
|
||||
),
|
||||
createBlock([
|
||||
createStatement(
|
||||
createCall(
|
||||
createIdentifier("factory"),
|
||||
createIdentifier("define"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createIdentifier("require"),
|
||||
createIdentifier("exports")
|
||||
createArrayLiteral([
|
||||
createLiteral("require"),
|
||||
createLiteral("exports"),
|
||||
...aliasedModuleNames,
|
||||
...unaliasedModuleNames
|
||||
]),
|
||||
createIdentifier("factory")
|
||||
]
|
||||
)
|
||||
)
|
||||
]
|
||||
),
|
||||
setEmitFlags(
|
||||
createIf(
|
||||
createStrictInequality(
|
||||
createIdentifier("v"),
|
||||
createIdentifier("undefined")
|
||||
),
|
||||
createStatement(
|
||||
createAssignment(
|
||||
createPropertyAccess(createIdentifier("module"), "exports"),
|
||||
createIdentifier("v")
|
||||
)
|
||||
)
|
||||
),
|
||||
EmitFlags.SingleLine
|
||||
])
|
||||
)
|
||||
]),
|
||||
createIf(
|
||||
createLogicalAnd(
|
||||
createTypeCheck(createIdentifier("define"), "function"),
|
||||
createPropertyAccess(createIdentifier("define"), "amd")
|
||||
),
|
||||
createBlock([
|
||||
createStatement(
|
||||
createCall(
|
||||
createIdentifier("define"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createArrayLiteral([
|
||||
createLiteral("require"),
|
||||
createLiteral("exports"),
|
||||
...aliasedModuleNames,
|
||||
...unaliasedModuleNames
|
||||
]),
|
||||
createIdentifier("factory")
|
||||
]
|
||||
)
|
||||
)
|
||||
])
|
||||
)
|
||||
)
|
||||
],
|
||||
/*location*/ undefined,
|
||||
/*multiLine*/ true
|
||||
],
|
||||
/*multiLine*/ true
|
||||
),
|
||||
/*location*/ undefined
|
||||
)
|
||||
);
|
||||
|
||||
@@ -274,8 +292,8 @@ namespace ts {
|
||||
|
||||
return updateSourceFileNode(
|
||||
node,
|
||||
createNodeArray(
|
||||
[
|
||||
setTextRange(
|
||||
createNodeArray([
|
||||
createStatement(
|
||||
createCall(
|
||||
umdHeader,
|
||||
@@ -300,7 +318,7 @@ namespace ts {
|
||||
]
|
||||
)
|
||||
)
|
||||
],
|
||||
]),
|
||||
/*location*/ node.statements
|
||||
)
|
||||
);
|
||||
@@ -341,15 +359,20 @@ namespace ts {
|
||||
|
||||
// Find the name of the module alias, if there is one
|
||||
const importAliasName = getLocalNameForExternalImport(importNode, currentSourceFile);
|
||||
if (includeNonAmdDependencies && importAliasName) {
|
||||
// Set emitFlags on the name of the classDeclaration
|
||||
// This is so that when printer will not substitute the identifier
|
||||
setEmitFlags(importAliasName, EmitFlags.NoSubstitution);
|
||||
aliasedModuleNames.push(externalModuleName);
|
||||
importAliasNames.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, importAliasName));
|
||||
}
|
||||
else {
|
||||
unaliasedModuleNames.push(externalModuleName);
|
||||
// It is possible that externalModuleName is undefined if it is not string literal.
|
||||
// This can happen in the invalid import syntax.
|
||||
// E.g : "import * from alias from 'someLib';"
|
||||
if (externalModuleName) {
|
||||
if (includeNonAmdDependencies && importAliasName) {
|
||||
// Set emitFlags on the name of the classDeclaration
|
||||
// This is so that when printer will not substitute the identifier
|
||||
setEmitFlags(importAliasName, EmitFlags.NoSubstitution);
|
||||
aliasedModuleNames.push(externalModuleName);
|
||||
importAliasNames.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, importAliasName));
|
||||
}
|
||||
else {
|
||||
unaliasedModuleNames.push(externalModuleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,20 +388,24 @@ namespace ts {
|
||||
startLexicalEnvironment();
|
||||
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
|
||||
const statementOffset = addPrologue(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
|
||||
|
||||
if (shouldEmitUnderscoreUnderscoreESModule()) {
|
||||
append(statements, createUnderscoreUnderscoreESModule());
|
||||
}
|
||||
|
||||
// Visit each statement of the module body.
|
||||
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
|
||||
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement));
|
||||
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
|
||||
|
||||
// Append the 'export =' statement if provided.
|
||||
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true);
|
||||
|
||||
// End the lexical environment for the module body
|
||||
// and merge any new lexical declarations.
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
|
||||
// Append the 'export =' statement if provided.
|
||||
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true);
|
||||
|
||||
const body = createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
|
||||
const body = createBlock(statements, /*multiLine*/ true);
|
||||
if (currentModuleInfo.hasExportStarsToExportValues) {
|
||||
// If we have any `export * from ...` declarations
|
||||
// we need to inform the emitter to add the __export helper.
|
||||
@@ -399,11 +426,8 @@ namespace ts {
|
||||
function addExportEqualsIfNeeded(statements: Statement[], emitAsReturn: boolean) {
|
||||
if (currentModuleInfo.exportEquals) {
|
||||
if (emitAsReturn) {
|
||||
const statement = createReturn(
|
||||
currentModuleInfo.exportEquals.expression,
|
||||
/*location*/ currentModuleInfo.exportEquals
|
||||
);
|
||||
|
||||
const statement = createReturn(currentModuleInfo.exportEquals.expression);
|
||||
setTextRange(statement, currentModuleInfo.exportEquals);
|
||||
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments);
|
||||
statements.push(statement);
|
||||
}
|
||||
@@ -415,10 +439,10 @@ namespace ts {
|
||||
"exports"
|
||||
),
|
||||
currentModuleInfo.exportEquals.expression
|
||||
),
|
||||
/*location*/ currentModuleInfo.exportEquals
|
||||
)
|
||||
);
|
||||
|
||||
setTextRange(statement, currentModuleInfo.exportEquals);
|
||||
setEmitFlags(statement, EmitFlags.NoComments);
|
||||
statements.push(statement);
|
||||
}
|
||||
@@ -481,7 +505,7 @@ namespace ts {
|
||||
if (moduleKind !== ModuleKind.AMD) {
|
||||
if (!node.importClause) {
|
||||
// import "mod";
|
||||
return createStatement(createRequireCall(node), /*location*/ node);
|
||||
return setTextRange(createStatement(createRequireCall(node)), node);
|
||||
}
|
||||
else {
|
||||
const variables: VariableDeclaration[] = [];
|
||||
@@ -520,12 +544,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
statements = append(statements,
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
variables,
|
||||
/*location*/ undefined,
|
||||
languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
|
||||
setTextRange(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
variables,
|
||||
languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
|
||||
)
|
||||
),
|
||||
/*location*/ node
|
||||
)
|
||||
@@ -539,14 +564,15 @@ namespace ts {
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
[
|
||||
createVariableDeclaration(
|
||||
getSynthesizedClone(namespaceDeclaration.name),
|
||||
/*type*/ undefined,
|
||||
getGeneratedNameForNode(node),
|
||||
setTextRange(
|
||||
createVariableDeclaration(
|
||||
getSynthesizedClone(namespaceDeclaration.name),
|
||||
/*type*/ undefined,
|
||||
getGeneratedNameForNode(node)
|
||||
),
|
||||
/*location*/ node
|
||||
)
|
||||
],
|
||||
/*location*/ undefined,
|
||||
languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
|
||||
)
|
||||
)
|
||||
@@ -592,31 +618,34 @@ namespace ts {
|
||||
if (moduleKind !== ModuleKind.AMD) {
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
statements = append(statements,
|
||||
createStatement(
|
||||
createExportExpression(
|
||||
node.name,
|
||||
createRequireCall(node)
|
||||
setTextRange(
|
||||
createStatement(
|
||||
createExportExpression(
|
||||
node.name,
|
||||
createRequireCall(node)
|
||||
)
|
||||
),
|
||||
/*location*/ node
|
||||
node
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
statements = append(statements,
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
[
|
||||
createVariableDeclaration(
|
||||
getSynthesizedClone(node.name),
|
||||
/*type*/ undefined,
|
||||
createRequireCall(node)
|
||||
)
|
||||
],
|
||||
/*location*/ undefined,
|
||||
/*flags*/ languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
|
||||
setTextRange(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(
|
||||
[
|
||||
createVariableDeclaration(
|
||||
getSynthesizedClone(node.name),
|
||||
/*type*/ undefined,
|
||||
createRequireCall(node)
|
||||
)
|
||||
],
|
||||
/*flags*/ languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
|
||||
)
|
||||
),
|
||||
/*location*/ node
|
||||
node
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -624,9 +653,11 @@ namespace ts {
|
||||
else {
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
statements = append(statements,
|
||||
createStatement(
|
||||
createExportExpression(getExportName(node), getLocalName(node)),
|
||||
/*location*/ node
|
||||
setTextRange(
|
||||
createStatement(
|
||||
createExportExpression(getExportName(node), getLocalName(node))
|
||||
),
|
||||
node
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -657,20 +688,23 @@ namespace ts {
|
||||
}
|
||||
|
||||
const generatedName = getGeneratedNameForNode(node);
|
||||
|
||||
if (node.exportClause) {
|
||||
const statements: Statement[] = [];
|
||||
// export { x, y } from "mod";
|
||||
if (moduleKind !== ModuleKind.AMD) {
|
||||
statements.push(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
generatedName,
|
||||
/*type*/ undefined,
|
||||
createRequireCall(node)
|
||||
)
|
||||
]),
|
||||
setTextRange(
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
generatedName,
|
||||
/*type*/ undefined,
|
||||
createRequireCall(node)
|
||||
)
|
||||
])
|
||||
),
|
||||
/*location*/ node
|
||||
)
|
||||
);
|
||||
@@ -681,9 +715,11 @@ namespace ts {
|
||||
specifier.propertyName || specifier.name
|
||||
);
|
||||
statements.push(
|
||||
createStatement(
|
||||
createExportExpression(getExportName(specifier), exportedValue),
|
||||
/*location*/ specifier
|
||||
setTextRange(
|
||||
createStatement(
|
||||
createExportExpression(getExportName(specifier), exportedValue)
|
||||
),
|
||||
specifier
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -692,17 +728,19 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
// export * from "mod";
|
||||
return createStatement(
|
||||
createCall(
|
||||
createIdentifier("__export"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
moduleKind !== ModuleKind.AMD
|
||||
? createRequireCall(node)
|
||||
: generatedName
|
||||
]
|
||||
return setTextRange(
|
||||
createStatement(
|
||||
createCall(
|
||||
createIdentifier("__export"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
moduleKind !== ModuleKind.AMD
|
||||
? createRequireCall(node)
|
||||
: generatedName
|
||||
]
|
||||
)
|
||||
),
|
||||
/*location*/ node
|
||||
node
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -741,15 +779,17 @@ namespace ts {
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
statements = append(statements,
|
||||
setOriginalNode(
|
||||
createFunctionDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
node.asteriskToken,
|
||||
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
|
||||
/*typeParameters*/ undefined,
|
||||
node.parameters,
|
||||
/*type*/ undefined,
|
||||
node.body,
|
||||
setTextRange(
|
||||
createFunctionDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
node.asteriskToken,
|
||||
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
|
||||
/*typeParameters*/ undefined,
|
||||
node.parameters,
|
||||
/*type*/ undefined,
|
||||
node.body
|
||||
),
|
||||
/*location*/ node
|
||||
),
|
||||
/*original*/ node
|
||||
@@ -782,16 +822,18 @@ namespace ts {
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
statements = append(statements,
|
||||
setOriginalNode(
|
||||
createClassDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
|
||||
/*typeParameters*/ undefined,
|
||||
node.heritageClauses,
|
||||
node.members,
|
||||
/*location*/ node
|
||||
setTextRange(
|
||||
createClassDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
|
||||
/*typeParameters*/ undefined,
|
||||
node.heritageClauses,
|
||||
node.members
|
||||
),
|
||||
node
|
||||
),
|
||||
/*original*/ node
|
||||
node
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -820,6 +862,7 @@ namespace ts {
|
||||
let statements: Statement[];
|
||||
let variables: VariableDeclaration[];
|
||||
let expressions: Expression[];
|
||||
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
let modifiers: NodeArray<Modifier>;
|
||||
|
||||
@@ -843,7 +886,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (expressions) {
|
||||
statements = append(statements, createStatement(inlineExpressions(expressions), /*location*/ node));
|
||||
statements = append(statements, setTextRange(createStatement(inlineExpressions(expressions)), node));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -880,9 +923,11 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
return createAssignment(
|
||||
createPropertyAccess(
|
||||
createIdentifier("exports"),
|
||||
node.name,
|
||||
setTextRange(
|
||||
createPropertyAccess(
|
||||
createIdentifier("exports"),
|
||||
node.name
|
||||
),
|
||||
/*location*/ node.name
|
||||
),
|
||||
node.initializer
|
||||
@@ -1107,43 +1152,39 @@ namespace ts {
|
||||
* @param allowComments Whether to allow comments on the export.
|
||||
*/
|
||||
function appendExportStatement(statements: Statement[] | undefined, exportName: Identifier, expression: Expression, location?: TextRange, allowComments?: boolean): Statement[] | undefined {
|
||||
if (exportName.text === "default") {
|
||||
const sourceFile = getOriginalNode(currentSourceFile, isSourceFile);
|
||||
if (sourceFile && !sourceFile.symbol.exports.get("___esModule")) {
|
||||
if (languageVersion === ScriptTarget.ES3) {
|
||||
statements = append(statements,
|
||||
createStatement(
|
||||
createExportExpression(
|
||||
createIdentifier("__esModule"),
|
||||
createLiteral(true)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
statements = append(statements,
|
||||
createStatement(
|
||||
createCall(
|
||||
createPropertyAccess(createIdentifier("Object"), "defineProperty"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createIdentifier("exports"),
|
||||
createLiteral("__esModule"),
|
||||
createObjectLiteral([
|
||||
createPropertyAssignment("value", createLiteral(true))
|
||||
])
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
statements = append(statements, createExportStatement(exportName, expression, location, allowComments));
|
||||
return statements;
|
||||
}
|
||||
|
||||
function createUnderscoreUnderscoreESModule() {
|
||||
let statement: Statement;
|
||||
if (languageVersion === ScriptTarget.ES3) {
|
||||
statement = createStatement(
|
||||
createExportExpression(
|
||||
createIdentifier("__esModule"),
|
||||
createLiteral(/*value*/ true)
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
statement = createStatement(
|
||||
createCall(
|
||||
createPropertyAccess(createIdentifier("Object"), "defineProperty"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createIdentifier("exports"),
|
||||
createLiteral("__esModule"),
|
||||
createObjectLiteral([
|
||||
createPropertyAssignment("value", createLiteral(/*value*/ true))
|
||||
])
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
setEmitFlags(statement, EmitFlags.CustomPrologue);
|
||||
return statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a call to the current file's export function to export a value.
|
||||
*
|
||||
@@ -1153,7 +1194,7 @@ namespace ts {
|
||||
* @param allowComments An optional value indicating whether to emit comments for the statement.
|
||||
*/
|
||||
function createExportStatement(name: Identifier, value: Expression, location?: TextRange, allowComments?: boolean) {
|
||||
const statement = createStatement(createExportExpression(name, value), location);
|
||||
const statement = setTextRange(createStatement(createExportExpression(name, value)), location);
|
||||
startOnNewLine(statement);
|
||||
if (!allowComments) {
|
||||
setEmitFlags(statement, EmitFlags.NoComments);
|
||||
@@ -1170,12 +1211,14 @@ namespace ts {
|
||||
* @param location The location to use for source maps and comments for the export.
|
||||
*/
|
||||
function createExportExpression(name: Identifier, value: Expression, location?: TextRange) {
|
||||
return createAssignment(
|
||||
createPropertyAccess(
|
||||
createIdentifier("exports"),
|
||||
getSynthesizedClone(name)
|
||||
return setTextRange(
|
||||
createAssignment(
|
||||
createPropertyAccess(
|
||||
createIdentifier("exports"),
|
||||
getSynthesizedClone(name)
|
||||
),
|
||||
value
|
||||
),
|
||||
value,
|
||||
location
|
||||
);
|
||||
}
|
||||
@@ -1207,24 +1250,24 @@ namespace ts {
|
||||
/**
|
||||
* Hook for node emit notifications.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to emit.
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
*/
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
|
||||
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
|
||||
if (node.kind === SyntaxKind.SourceFile) {
|
||||
currentSourceFile = <SourceFile>node;
|
||||
currentModuleInfo = moduleInfoMap[getOriginalNodeId(currentSourceFile)];
|
||||
noSubstitution = [];
|
||||
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentModuleInfo = undefined;
|
||||
noSubstitution = undefined;
|
||||
}
|
||||
else {
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1235,16 +1278,16 @@ namespace ts {
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to substitute.
|
||||
*/
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
function onSubstituteNode(hint: EmitHint, node: Node) {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (node.id && noSubstitution[node.id]) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
if (hint === EmitHint.Expression) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
else if (isShorthandPropertyAssignment(node)) {
|
||||
@@ -1268,9 +1311,9 @@ namespace ts {
|
||||
// destructuring assignment
|
||||
if (node.objectAssignmentInitializer) {
|
||||
const initializer = createAssignment(exportedOrImportedName, node.objectAssignmentInitializer);
|
||||
return createPropertyAssignment(name, initializer, /*location*/ node);
|
||||
return setTextRange(createPropertyAssignment(name, initializer), node);
|
||||
}
|
||||
return createPropertyAssignment(name, exportedOrImportedName, /*location*/ node);
|
||||
return setTextRange(createPropertyAssignment(name, exportedOrImportedName), node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
@@ -1306,15 +1349,18 @@ namespace ts {
|
||||
if (externalHelpersModuleName) {
|
||||
return createPropertyAccess(externalHelpersModuleName, node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
if (!isGeneratedIdentifier(node) && !isLocalName(node)) {
|
||||
const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node));
|
||||
if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) {
|
||||
return createPropertyAccess(
|
||||
createIdentifier("exports"),
|
||||
getSynthesizedClone(node),
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
createIdentifier("exports"),
|
||||
getSynthesizedClone(node)
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
@@ -1322,17 +1368,21 @@ namespace ts {
|
||||
const importDeclaration = resolver.getReferencedImportDeclaration(node);
|
||||
if (importDeclaration) {
|
||||
if (isImportClause(importDeclaration)) {
|
||||
return createPropertyAccess(
|
||||
getGeneratedNameForNode(importDeclaration.parent),
|
||||
createIdentifier("default"),
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
getGeneratedNameForNode(importDeclaration.parent),
|
||||
createIdentifier("default")
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
else if (isImportSpecifier(importDeclaration)) {
|
||||
const name = importDeclaration.propertyName || importDeclaration.name;
|
||||
return createPropertyAccess(
|
||||
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
|
||||
getSynthesizedClone(name),
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
|
||||
getSynthesizedClone(name)
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
@@ -1400,10 +1450,12 @@ namespace ts {
|
||||
const exportedNames = getExports(node.operand);
|
||||
if (exportedNames) {
|
||||
let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression
|
||||
? createBinary(
|
||||
node.operand,
|
||||
createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken),
|
||||
createLiteral(1),
|
||||
? setTextRange(
|
||||
createBinary(
|
||||
node.operand,
|
||||
createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken),
|
||||
createLiteral(1)
|
||||
),
|
||||
/*location*/ node)
|
||||
: node;
|
||||
for (const exportName of exportedNames) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../factory.ts" />
|
||||
/// <reference path="../../visitor.ts" />
|
||||
/// <reference path="../destructuring.ts" />
|
||||
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
@@ -105,17 +106,20 @@ namespace ts {
|
||||
const updated = setEmitFlags(
|
||||
updateSourceFileNode(
|
||||
node,
|
||||
createNodeArray([
|
||||
createStatement(
|
||||
createCall(
|
||||
createPropertyAccess(createIdentifier("System"), "register"),
|
||||
/*typeArguments*/ undefined,
|
||||
moduleName
|
||||
? [moduleName, dependencies, moduleBodyFunction]
|
||||
: [dependencies, moduleBodyFunction]
|
||||
setTextRange(
|
||||
createNodeArray([
|
||||
createStatement(
|
||||
createCall(
|
||||
createPropertyAccess(createIdentifier("System"), "register"),
|
||||
/*typeArguments*/ undefined,
|
||||
moduleName
|
||||
? [moduleName, dependencies, moduleBodyFunction]
|
||||
: [dependencies, moduleBodyFunction]
|
||||
)
|
||||
)
|
||||
)
|
||||
], node.statements)
|
||||
]),
|
||||
node.statements
|
||||
)
|
||||
), EmitFlags.NoTrailingComments);
|
||||
|
||||
if (!(compilerOptions.outFile || compilerOptions.out)) {
|
||||
@@ -133,7 +137,6 @@ namespace ts {
|
||||
contextObject = undefined;
|
||||
hoistedStatements = undefined;
|
||||
enclosingBlockScopedContainer = undefined;
|
||||
|
||||
return aggregateTransformFlags(updated);
|
||||
}
|
||||
|
||||
@@ -148,18 +151,20 @@ namespace ts {
|
||||
for (let i = 0; i < externalImports.length; i++) {
|
||||
const externalImport = externalImports[i];
|
||||
const externalModuleName = getExternalModuleNameLiteral(externalImport, currentSourceFile, host, resolver, compilerOptions);
|
||||
const text = externalModuleName.text;
|
||||
const groupIndex = groupIndices.get(text);
|
||||
if (groupIndex !== undefined) {
|
||||
// deduplicate/group entries in dependency list by the dependency name
|
||||
dependencyGroups[groupIndex].externalImports.push(externalImport);
|
||||
}
|
||||
else {
|
||||
groupIndices.set(text, dependencyGroups.length);
|
||||
dependencyGroups.push({
|
||||
name: externalModuleName,
|
||||
externalImports: [externalImport]
|
||||
});
|
||||
if (externalModuleName) {
|
||||
const text = externalModuleName.text;
|
||||
const groupIndex = groupIndices.get(text);
|
||||
if (groupIndex !== undefined) {
|
||||
// deduplicate/group entries in dependency list by the dependency name
|
||||
dependencyGroups[groupIndex].externalImports.push(externalImport);
|
||||
}
|
||||
else {
|
||||
groupIndices.set(text, dependencyGroups.length);
|
||||
dependencyGroups.push({
|
||||
name: externalModuleName,
|
||||
externalImports: [externalImport]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +227,8 @@ namespace ts {
|
||||
startLexicalEnvironment();
|
||||
|
||||
// Add any prologue directives.
|
||||
const statementOffset = addPrologueDirectives(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor);
|
||||
const ensureUseStrict = compilerOptions.alwaysStrict || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile));
|
||||
const statementOffset = addPrologue(statements, node.statements, ensureUseStrict, sourceElementVisitor);
|
||||
|
||||
// var __moduleName = context_1 && context_1.id;
|
||||
statements.push(
|
||||
@@ -242,7 +248,7 @@ namespace ts {
|
||||
);
|
||||
|
||||
// Visit the synthetic external helpers import declaration if present
|
||||
visitNode(moduleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true);
|
||||
visitNode(moduleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement);
|
||||
|
||||
// Visit the statements of the source file, emitting any transformations into
|
||||
// the `executeStatements` array. We do this *before* we fill the `setters` array
|
||||
@@ -260,35 +266,26 @@ namespace ts {
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
|
||||
const exportStarFunction = addExportStarIfNeeded(statements);
|
||||
statements.push(
|
||||
createReturn(
|
||||
setMultiLine(
|
||||
createObjectLiteral([
|
||||
createPropertyAssignment("setters",
|
||||
createSettersArray(exportStarFunction, dependencyGroups)
|
||||
),
|
||||
createPropertyAssignment("execute",
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
/*parameters*/ [],
|
||||
/*type*/ undefined,
|
||||
createBlock(
|
||||
executeStatements,
|
||||
/*location*/ undefined,
|
||||
/*multiLine*/ true
|
||||
)
|
||||
)
|
||||
)
|
||||
]),
|
||||
/*multiLine*/ true
|
||||
const moduleObject = createObjectLiteral([
|
||||
createPropertyAssignment("setters",
|
||||
createSettersArray(exportStarFunction, dependencyGroups)
|
||||
),
|
||||
createPropertyAssignment("execute",
|
||||
createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
/*parameters*/ [],
|
||||
/*type*/ undefined,
|
||||
createBlock(executeStatements, /*multiLine*/ true)
|
||||
)
|
||||
)
|
||||
);
|
||||
]);
|
||||
|
||||
return createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
|
||||
moduleObject.multiLine = true;
|
||||
statements.push(createReturn(moduleObject));
|
||||
return createBlock(statements, /*multiLine*/ true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -337,7 +334,7 @@ namespace ts {
|
||||
exportedNames.push(
|
||||
createPropertyAssignment(
|
||||
createLiteral(exportedLocalName),
|
||||
createLiteral(true)
|
||||
createTrue()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -359,7 +356,7 @@ namespace ts {
|
||||
exportedNames.push(
|
||||
createPropertyAssignment(
|
||||
createLiteral((element.name || element.propertyName).text),
|
||||
createLiteral(true)
|
||||
createTrue()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -373,7 +370,7 @@ namespace ts {
|
||||
createVariableDeclaration(
|
||||
exportedNamesStorageRef,
|
||||
/*type*/ undefined,
|
||||
createObjectLiteral(exportedNames, /*location*/ undefined, /*multiline*/ true)
|
||||
createObjectLiteral(exportedNames, /*multiline*/ true)
|
||||
)
|
||||
])
|
||||
)
|
||||
@@ -456,9 +453,7 @@ namespace ts {
|
||||
[exports]
|
||||
)
|
||||
)
|
||||
],
|
||||
/*location*/ undefined,
|
||||
/*multiline*/ true)
|
||||
], /*multiline*/ true)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -525,7 +520,7 @@ namespace ts {
|
||||
createCall(
|
||||
exportFunction,
|
||||
/*typeArguments*/ undefined,
|
||||
[createObjectLiteral(properties, /*location*/ undefined, /*multiline*/ true)]
|
||||
[createObjectLiteral(properties, /*multiline*/ true)]
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -558,12 +553,12 @@ namespace ts {
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)],
|
||||
/*type*/ undefined,
|
||||
createBlock(statements, /*location*/ undefined, /*multiLine*/ true)
|
||||
createBlock(statements, /*multiLine*/ true)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return createArrayLiteral(setters, /*location*/ undefined, /*multiLine*/ true);
|
||||
return createArrayLiteral(setters, /*multiLine*/ true);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -677,6 +672,7 @@ namespace ts {
|
||||
node,
|
||||
node.decorators,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
node.asteriskToken,
|
||||
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.parameters, destructuringVisitor, isParameterDeclaration),
|
||||
@@ -713,19 +709,23 @@ namespace ts {
|
||||
|
||||
// Rewrite the class declaration into an assignment of a class expression.
|
||||
statements = append(statements,
|
||||
createStatement(
|
||||
createAssignment(
|
||||
name,
|
||||
createClassExpression(
|
||||
/*modifiers*/ undefined,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.heritageClauses, destructuringVisitor, isHeritageClause),
|
||||
visitNodes(node.members, destructuringVisitor, isClassElement),
|
||||
/*location*/ node
|
||||
setTextRange(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
name,
|
||||
setTextRange(
|
||||
createClassExpression(
|
||||
/*modifiers*/ undefined,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.heritageClauses, destructuringVisitor, isHeritageClause),
|
||||
visitNodes(node.members, destructuringVisitor, isClassElement)
|
||||
),
|
||||
node
|
||||
)
|
||||
)
|
||||
),
|
||||
/*location*/ node
|
||||
node
|
||||
)
|
||||
);
|
||||
|
||||
@@ -766,7 +766,7 @@ namespace ts {
|
||||
|
||||
let statements: Statement[];
|
||||
if (expressions) {
|
||||
statements = append(statements, createStatement(inlineExpressions(expressions), /*location*/ node));
|
||||
statements = append(statements, setTextRange(createStatement(inlineExpressions(expressions)), node));
|
||||
}
|
||||
|
||||
if (isMarkedDeclaration) {
|
||||
@@ -864,8 +864,8 @@ namespace ts {
|
||||
function createVariableAssignment(name: Identifier, value: Expression, location: TextRange, isExportedDeclaration: boolean) {
|
||||
hoistVariableDeclaration(getSynthesizedClone(name));
|
||||
return isExportedDeclaration
|
||||
? createExportExpression(name, preventSubstitution(createAssignment(name, value, location)))
|
||||
: preventSubstitution(createAssignment(name, value, location));
|
||||
? createExportExpression(name, preventSubstitution(setTextRange(createAssignment(name, value), location)))
|
||||
: preventSubstitution(setTextRange(createAssignment(name, value), location));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1222,8 +1222,8 @@ namespace ts {
|
||||
node = updateFor(
|
||||
node,
|
||||
visitForInitializer(node.initializer),
|
||||
visitNode(node.condition, destructuringVisitor, isExpression, /*optional*/ true),
|
||||
visitNode(node.incrementor, destructuringVisitor, isExpression, /*optional*/ true),
|
||||
visitNode(node.condition, destructuringVisitor, isExpression),
|
||||
visitNode(node.incrementor, destructuringVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement)
|
||||
);
|
||||
|
||||
@@ -1244,7 +1244,7 @@ namespace ts {
|
||||
node,
|
||||
visitForInitializer(node.initializer),
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
|
||||
);
|
||||
|
||||
enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer;
|
||||
@@ -1262,9 +1262,10 @@ namespace ts {
|
||||
|
||||
node = updateForOf(
|
||||
node,
|
||||
node.awaitModifier,
|
||||
visitForInitializer(node.initializer),
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
|
||||
);
|
||||
|
||||
enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer;
|
||||
@@ -1288,6 +1289,10 @@ namespace ts {
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function visitForInitializer(node: ForInitializer): ForInitializer {
|
||||
if (!node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (shouldHoistForInitializer(node)) {
|
||||
let expressions: Expression[];
|
||||
for (const variable of node.declarations) {
|
||||
@@ -1309,7 +1314,7 @@ namespace ts {
|
||||
function visitDoStatement(node: DoStatement): VisitResult<Statement> {
|
||||
return updateDo(
|
||||
node,
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock),
|
||||
visitNode(node.expression, destructuringVisitor, isExpression)
|
||||
);
|
||||
}
|
||||
@@ -1323,7 +1328,7 @@ namespace ts {
|
||||
return updateWhile(
|
||||
node,
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1336,7 +1341,7 @@ namespace ts {
|
||||
return updateLabel(
|
||||
node,
|
||||
node.label,
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1349,7 +1354,7 @@ namespace ts {
|
||||
return updateWith(
|
||||
node,
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1496,7 +1501,7 @@ namespace ts {
|
||||
* @param node The destructuring target.
|
||||
*/
|
||||
function hasExportedReferenceInDestructuringTarget(node: Expression | ObjectLiteralElementLike): boolean {
|
||||
if (isAssignmentExpression(node)) {
|
||||
if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) {
|
||||
return hasExportedReferenceInDestructuringTarget(node.left);
|
||||
}
|
||||
else if (isSpreadExpression(node)) {
|
||||
@@ -1548,11 +1553,11 @@ namespace ts {
|
||||
/**
|
||||
* Hook for node emit notifications.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to emit.
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
* @param emitCallback A callback used to emit the node in the printer.
|
||||
*/
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
|
||||
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
|
||||
if (node.kind === SyntaxKind.SourceFile) {
|
||||
const id = getOriginalNodeId(node);
|
||||
currentSourceFile = <SourceFile>node;
|
||||
@@ -1564,7 +1569,7 @@ namespace ts {
|
||||
delete noSubstitutionMap[id];
|
||||
}
|
||||
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
|
||||
currentSourceFile = undefined;
|
||||
moduleInfo = undefined;
|
||||
@@ -1572,7 +1577,7 @@ namespace ts {
|
||||
noSubstitution = undefined;
|
||||
}
|
||||
else {
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1583,16 +1588,16 @@ namespace ts {
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to substitute.
|
||||
*/
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
function onSubstituteNode(hint: EmitHint, node: Node) {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (isSubstitutionPrevented(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
if (hint === EmitHint.Expression) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
|
||||
@@ -1629,6 +1634,7 @@ namespace ts {
|
||||
if (externalHelpersModuleName) {
|
||||
return createPropertyAccess(externalHelpersModuleName, node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1642,16 +1648,20 @@ namespace ts {
|
||||
const importDeclaration = resolver.getReferencedImportDeclaration(node);
|
||||
if (importDeclaration) {
|
||||
if (isImportClause(importDeclaration)) {
|
||||
return createPropertyAccess(
|
||||
getGeneratedNameForNode(importDeclaration.parent),
|
||||
createIdentifier("default"),
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
getGeneratedNameForNode(importDeclaration.parent),
|
||||
createIdentifier("default")
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
else if (isImportSpecifier(importDeclaration)) {
|
||||
return createPropertyAccess(
|
||||
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
|
||||
getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name),
|
||||
return setTextRange(
|
||||
createPropertyAccess(
|
||||
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
|
||||
getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name)
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
@@ -1718,10 +1728,13 @@ namespace ts {
|
||||
const exportedNames = getExports(node.operand);
|
||||
if (exportedNames) {
|
||||
let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression
|
||||
? createPrefix(
|
||||
node.operator,
|
||||
node.operand,
|
||||
/*location*/ node)
|
||||
? setTextRange(
|
||||
createPrefix(
|
||||
node.operator,
|
||||
node.operand
|
||||
),
|
||||
node
|
||||
)
|
||||
: node;
|
||||
|
||||
for (const exportName of exportedNames) {
|
||||
|
||||
+240
-180
@@ -1,4 +1,4 @@
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../factory.ts" />
|
||||
/// <reference path="../visitor.ts" />
|
||||
/// <reference path="./destructuring.ts" />
|
||||
|
||||
@@ -472,7 +472,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitSourceFile(node: SourceFile) {
|
||||
const alwaysStrict = compilerOptions.alwaysStrict && !(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
|
||||
const alwaysStrict = (compilerOptions.alwaysStrict === undefined ? compilerOptions.strict : compilerOptions.alwaysStrict) &&
|
||||
!(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
|
||||
return updateSourceFileNode(
|
||||
node,
|
||||
visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict));
|
||||
@@ -588,17 +589,17 @@ namespace ts {
|
||||
name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.heritageClauses, visitor, isHeritageClause),
|
||||
transformClassMembers(node, hasExtendsClause),
|
||||
node);
|
||||
|
||||
let emitFlags = getEmitFlags(node);
|
||||
transformClassMembers(node, hasExtendsClause)
|
||||
);
|
||||
|
||||
// To better align with the old emitter, we should not emit a trailing source map
|
||||
// entry if the class has static properties.
|
||||
let emitFlags = getEmitFlags(node);
|
||||
if (hasStaticProperties) {
|
||||
emitFlags |= EmitFlags.NoTrailingSourceMap;
|
||||
}
|
||||
|
||||
setTextRange(classDeclaration, node);
|
||||
setOriginalNode(classDeclaration, node);
|
||||
setEmitFlags(classDeclaration, emitFlags);
|
||||
return classDeclaration;
|
||||
@@ -709,13 +710,24 @@ namespace ts {
|
||||
// }
|
||||
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
|
||||
const members = transformClassMembers(node, hasExtendsClause);
|
||||
const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members, location);
|
||||
const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members);
|
||||
setOriginalNode(classExpression, node);
|
||||
setTextRange(classExpression, location);
|
||||
|
||||
// let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference
|
||||
// or decoratedClassAlias if the class contain self-reference.
|
||||
const statement = createLetStatement(declName, classAlias ? createAssignment(classAlias, classExpression) : classExpression, location);
|
||||
const statement = createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
declName,
|
||||
/*type*/ undefined,
|
||||
classAlias ? createAssignment(classAlias, classExpression) : classExpression
|
||||
)
|
||||
], NodeFlags.Let)
|
||||
);
|
||||
setOriginalNode(statement, node);
|
||||
setTextRange(statement, location);
|
||||
setCommentRange(statement, node);
|
||||
return statement;
|
||||
}
|
||||
@@ -734,18 +746,17 @@ namespace ts {
|
||||
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
|
||||
const members = transformClassMembers(node, some(heritageClauses, c => c.token === SyntaxKind.ExtendsKeyword));
|
||||
|
||||
const classExpression = setOriginalNode(
|
||||
createClassExpression(
|
||||
/*modifiers*/ undefined,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
heritageClauses,
|
||||
members,
|
||||
/*location*/ node
|
||||
),
|
||||
node
|
||||
const classExpression = createClassExpression(
|
||||
/*modifiers*/ undefined,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
heritageClauses,
|
||||
members
|
||||
);
|
||||
|
||||
setOriginalNode(classExpression, node);
|
||||
setTextRange(classExpression, node);
|
||||
|
||||
if (staticProperties.length > 0) {
|
||||
const expressions: Expression[] = [];
|
||||
const temp = createTempVariable(hoistVariableDeclaration);
|
||||
@@ -781,7 +792,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
addRange(members, visitNodes(node.members, classElementVisitor, isClassElement));
|
||||
return createNodeArray(members, /*location*/ node.members);
|
||||
return setTextRange(createNodeArray(members), /*location*/ node.members);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -812,12 +823,14 @@ namespace ts {
|
||||
// }
|
||||
return startOnNewLine(
|
||||
setOriginalNode(
|
||||
createConstructor(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
parameters,
|
||||
body,
|
||||
/*location*/ constructor || node
|
||||
setTextRange(
|
||||
createConstructor(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
parameters,
|
||||
body
|
||||
),
|
||||
constructor || node
|
||||
),
|
||||
constructor
|
||||
)
|
||||
@@ -860,7 +873,7 @@ namespace ts {
|
||||
* @param hasExtendsClause A value indicating whether the class has an extends clause.
|
||||
*/
|
||||
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, hasExtendsClause: boolean) {
|
||||
const statements: Statement[] = [];
|
||||
let statements: Statement[] = [];
|
||||
let indexOfFirstStatement = 0;
|
||||
|
||||
resumeLexicalEnvironment();
|
||||
@@ -918,14 +931,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
// End the lexical environment.
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
return createBlock(
|
||||
createNodeArray(
|
||||
statements,
|
||||
/*location*/ constructor ? constructor.body.statements : node.members
|
||||
statements = mergeLexicalEnvironment(statements, endLexicalEnvironment());
|
||||
return setTextRange(
|
||||
createBlock(
|
||||
setTextRange(
|
||||
createNodeArray(statements),
|
||||
/*location*/ constructor ? constructor.body.statements : node.members
|
||||
),
|
||||
/*multiLine*/ true
|
||||
),
|
||||
/*location*/ constructor ? constructor.body : /*location*/ undefined,
|
||||
/*multiLine*/ true
|
||||
/*location*/ constructor ? constructor.body : undefined
|
||||
);
|
||||
}
|
||||
|
||||
@@ -939,7 +954,7 @@ namespace ts {
|
||||
if (ctor.body) {
|
||||
const statements = ctor.body.statements;
|
||||
// add prologue directives to the list (if any)
|
||||
const index = addPrologueDirectives(result, statements, /*ensureUseStrict*/ false, visitor);
|
||||
const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor);
|
||||
if (index === statements.length) {
|
||||
// list contains nothing but prologue directives (or empty) - exit
|
||||
return index;
|
||||
@@ -991,16 +1006,20 @@ namespace ts {
|
||||
setEmitFlags(localName, EmitFlags.NoComments);
|
||||
|
||||
return startOnNewLine(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
createPropertyAccess(
|
||||
createThis(),
|
||||
propertyName,
|
||||
/*location*/ node.name
|
||||
),
|
||||
localName
|
||||
setTextRange(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
setTextRange(
|
||||
createPropertyAccess(
|
||||
createThis(),
|
||||
propertyName
|
||||
),
|
||||
node.name
|
||||
),
|
||||
localName
|
||||
)
|
||||
),
|
||||
/*location*/ moveRangePos(node, -1)
|
||||
moveRangePos(node, -1)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -1504,7 +1523,7 @@ namespace ts {
|
||||
(properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node))));
|
||||
}
|
||||
if (properties) {
|
||||
decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
|
||||
decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", createObjectLiteral(properties, /*multiLine*/ true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1633,7 +1652,7 @@ namespace ts {
|
||||
if (isFunctionLike(node) && node.type) {
|
||||
return serializeTypeNode(node.type);
|
||||
}
|
||||
else if (isAsyncFunctionLike(node)) {
|
||||
else if (isAsyncFunction(node)) {
|
||||
return createIdentifier("Promise");
|
||||
}
|
||||
|
||||
@@ -1688,6 +1707,9 @@ namespace ts {
|
||||
case SyntaxKind.StringKeyword:
|
||||
return createIdentifier("String");
|
||||
|
||||
case SyntaxKind.ObjectKeyword:
|
||||
return createIdentifier("Object");
|
||||
|
||||
case SyntaxKind.LiteralType:
|
||||
switch ((<LiteralTypeNode>node).literal.kind) {
|
||||
case SyntaxKind.StringLiteral:
|
||||
@@ -1941,10 +1963,7 @@ namespace ts {
|
||||
expression = createAssignment(generatedName, expression);
|
||||
}
|
||||
|
||||
return setOriginalNode(
|
||||
createComputedPropertyName(expression, /*location*/ name),
|
||||
name
|
||||
);
|
||||
return updateComputedPropertyName(name, expression);
|
||||
}
|
||||
else {
|
||||
return name;
|
||||
@@ -1963,9 +1982,11 @@ namespace ts {
|
||||
function visitHeritageClause(node: HeritageClause): HeritageClause {
|
||||
if (node.token === SyntaxKind.ExtendsKeyword) {
|
||||
const types = visitNodes(node.types, visitor, isExpressionWithTypeArguments, 0, 1);
|
||||
return createHeritageClause(
|
||||
SyntaxKind.ExtendsKeyword,
|
||||
types,
|
||||
return setTextRange(
|
||||
createHeritageClause(
|
||||
SyntaxKind.ExtendsKeyword,
|
||||
types
|
||||
),
|
||||
node
|
||||
);
|
||||
}
|
||||
@@ -1982,11 +2003,10 @@ namespace ts {
|
||||
* @param node The ExpressionWithTypeArguments to transform.
|
||||
*/
|
||||
function visitExpressionWithTypeArguments(node: ExpressionWithTypeArguments): ExpressionWithTypeArguments {
|
||||
const expression = visitNode(node.expression, visitor, isLeftHandSideExpression);
|
||||
return createExpressionWithTypeArguments(
|
||||
return updateExpressionWithTypeArguments(
|
||||
node,
|
||||
/*typeArguments*/ undefined,
|
||||
expression,
|
||||
node
|
||||
visitNode(node.expression, visitor, isLeftHandSideExpression)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2005,7 +2025,13 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return visitEachChild(node, visitor, context);
|
||||
return updateConstructor(
|
||||
node,
|
||||
visitNodes(node.decorators, visitor, isDecorator),
|
||||
visitNodes(node.modifiers, visitor, isModifier),
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
visitFunctionBody(node.body, visitor, context)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2026,7 +2052,9 @@ namespace ts {
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
node.asteriskToken,
|
||||
visitPropertyNameOfClassElement(node),
|
||||
/*questionToken*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
@@ -2130,6 +2158,7 @@ namespace ts {
|
||||
node,
|
||||
/*decorators*/ undefined,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
node.asteriskToken,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
@@ -2153,17 +2182,18 @@ namespace ts {
|
||||
* @param node The function expression node.
|
||||
*/
|
||||
function visitFunctionExpression(node: FunctionExpression): Expression {
|
||||
if (nodeIsMissing(node.body)) {
|
||||
if (!shouldEmitFunctionLikeDeclaration(node)) {
|
||||
return createOmittedExpression();
|
||||
}
|
||||
const updated = updateFunctionExpression(
|
||||
node,
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
node.asteriskToken,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitParameterList(node.parameters, visitor, context),
|
||||
/*type*/ undefined,
|
||||
visitFunctionBody(node.body, visitor, context)
|
||||
visitFunctionBody(node.body, visitor, context) || createBlock([])
|
||||
);
|
||||
return updated;
|
||||
}
|
||||
@@ -2207,13 +2237,13 @@ namespace ts {
|
||||
visitNode(node.name, visitor, isBindingName),
|
||||
/*questionToken*/ undefined,
|
||||
/*type*/ undefined,
|
||||
visitNode(node.initializer, visitor, isExpression),
|
||||
/*location*/ moveRangePastModifiers(node)
|
||||
visitNode(node.initializer, visitor, isExpression)
|
||||
);
|
||||
|
||||
// While we emit the source map for the node after skipping decorators and modifiers,
|
||||
// we need to emit the comments for the original range.
|
||||
setOriginalNode(parameter, node);
|
||||
setTextRange(parameter, moveRangePastModifiers(node));
|
||||
setCommentRange(parameter, node);
|
||||
setSourceMapRange(parameter, moveRangePastModifiers(node));
|
||||
setEmitFlags(parameter.name, EmitFlags.NoTrailingSourceMap);
|
||||
@@ -2235,11 +2265,13 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return createStatement(
|
||||
inlineExpressions(
|
||||
map(variables, transformInitializedVariable)
|
||||
return setTextRange(
|
||||
createStatement(
|
||||
inlineExpressions(
|
||||
map(variables, transformInitializedVariable)
|
||||
)
|
||||
),
|
||||
/*location*/ node
|
||||
node
|
||||
);
|
||||
}
|
||||
else {
|
||||
@@ -2260,9 +2292,11 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
else {
|
||||
return createAssignment(
|
||||
getNamespaceMemberNameWithSourceMapsAndWithoutComments(name),
|
||||
visitNode(node.initializer, visitor, isExpression),
|
||||
return setTextRange(
|
||||
createAssignment(
|
||||
getNamespaceMemberNameWithSourceMapsAndWithoutComments(name),
|
||||
visitNode(node.initializer, visitor, isExpression)
|
||||
),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
@@ -2295,13 +2329,13 @@ namespace ts {
|
||||
// code if the casted expression has a lower precedence than the rest of the
|
||||
// expression.
|
||||
//
|
||||
// To preserve comments, we return a "PartiallyEmittedExpression" here which will
|
||||
// preserve the position information of the original expression.
|
||||
//
|
||||
// Due to the auto-parenthesization rules used by the visitor and factory functions
|
||||
// we can safely elide the parentheses here, as a new synthetic
|
||||
// ParenthesizedExpression will be inserted if we remove parentheses too
|
||||
// aggressively.
|
||||
//
|
||||
// To preserve comments, we return a "PartiallyEmittedExpression" here which will
|
||||
// preserve the position information of the original expression.
|
||||
return createPartiallyEmittedExpression(expression, node);
|
||||
}
|
||||
|
||||
@@ -2420,11 +2454,11 @@ namespace ts {
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
[moduleArg]
|
||||
),
|
||||
/*location*/ node
|
||||
)
|
||||
);
|
||||
|
||||
setOriginalNode(enumStatement, node);
|
||||
setTextRange(enumStatement, node);
|
||||
setEmitFlags(enumStatement, emitFlags);
|
||||
statements.push(enumStatement);
|
||||
|
||||
@@ -2450,8 +2484,7 @@ namespace ts {
|
||||
|
||||
currentNamespaceContainerName = savedCurrentNamespaceLocalName;
|
||||
return createBlock(
|
||||
createNodeArray(statements, /*location*/ node.members),
|
||||
/*location*/ undefined,
|
||||
setTextRange(createNodeArray(statements), /*location*/ node.members),
|
||||
/*multiLine*/ true
|
||||
);
|
||||
}
|
||||
@@ -2466,22 +2499,26 @@ namespace ts {
|
||||
// we pass false as 'generateNameForComputedPropertyName' for a backward compatibility purposes
|
||||
// old emitter always generate 'expression' part of the name as-is.
|
||||
const name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false);
|
||||
return createStatement(
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
currentNamespaceContainerName,
|
||||
return setTextRange(
|
||||
createStatement(
|
||||
setTextRange(
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
currentNamespaceContainerName,
|
||||
name
|
||||
createAssignment(
|
||||
createElementAccess(
|
||||
currentNamespaceContainerName,
|
||||
name
|
||||
),
|
||||
transformEnumMemberDeclarationValue(member)
|
||||
)
|
||||
),
|
||||
transformEnumMemberDeclarationValue(member)
|
||||
)
|
||||
),
|
||||
name,
|
||||
/*location*/ member
|
||||
name
|
||||
),
|
||||
member
|
||||
)
|
||||
),
|
||||
/*location*/ member
|
||||
member
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2699,11 +2736,11 @@ namespace ts {
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
[moduleArg]
|
||||
),
|
||||
/*location*/ node
|
||||
)
|
||||
);
|
||||
|
||||
setOriginalNode(moduleStatement, node);
|
||||
setTextRange(moduleStatement, node);
|
||||
setEmitFlags(moduleStatement, emitFlags);
|
||||
statements.push(moduleStatement);
|
||||
|
||||
@@ -2758,13 +2795,13 @@ namespace ts {
|
||||
currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName;
|
||||
|
||||
const block = createBlock(
|
||||
createNodeArray(
|
||||
statements,
|
||||
setTextRange(
|
||||
createNodeArray(statements),
|
||||
/*location*/ statementsLocation
|
||||
),
|
||||
/*location*/ blockLocation,
|
||||
/*multiLine*/ true
|
||||
);
|
||||
setTextRange(block, blockLocation);
|
||||
|
||||
// namespace hello.hi.world {
|
||||
// function foo() {}
|
||||
@@ -2812,7 +2849,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Elide the declaration if the import clause was elided.
|
||||
const importClause = visitNode(node.importClause, visitImportClause, isImportClause, /*optional*/ true);
|
||||
const importClause = visitNode(node.importClause, visitImportClause, isImportClause);
|
||||
return importClause
|
||||
? updateImportDeclaration(
|
||||
node,
|
||||
@@ -2831,7 +2868,7 @@ namespace ts {
|
||||
function visitImportClause(node: ImportClause): VisitResult<ImportClause> {
|
||||
// Elide the import clause if we elide both its name and its named bindings.
|
||||
const name = resolver.isReferencedAliasDeclaration(node) ? node.name : undefined;
|
||||
const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings, /*optional*/ true);
|
||||
const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings);
|
||||
return (name || namedBindings) ? updateImportClause(node, name, namedBindings) : undefined;
|
||||
}
|
||||
|
||||
@@ -2893,7 +2930,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Elide the export declaration if all of its named exports are elided.
|
||||
const exportClause = visitNode(node.exportClause, visitNamedExports, isNamedExports, /*optional*/ true);
|
||||
const exportClause = visitNode(node.exportClause, visitNamedExports, isNamedExports);
|
||||
return exportClause
|
||||
? updateExportDeclaration(
|
||||
node,
|
||||
@@ -2964,18 +3001,20 @@ namespace ts {
|
||||
// export var ${name} = ${moduleReference};
|
||||
// var ${name} = ${moduleReference};
|
||||
return setOriginalNode(
|
||||
createVariableStatement(
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
createVariableDeclarationList([
|
||||
setOriginalNode(
|
||||
createVariableDeclaration(
|
||||
node.name,
|
||||
/*type*/ undefined,
|
||||
moduleReference
|
||||
),
|
||||
node
|
||||
)
|
||||
]),
|
||||
setTextRange(
|
||||
createVariableStatement(
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
createVariableDeclarationList([
|
||||
setOriginalNode(
|
||||
createVariableDeclaration(
|
||||
node.name,
|
||||
/*type*/ undefined,
|
||||
moduleReference
|
||||
),
|
||||
node
|
||||
)
|
||||
])
|
||||
),
|
||||
node
|
||||
),
|
||||
node
|
||||
@@ -3036,7 +3075,7 @@ namespace ts {
|
||||
* Creates a statement for the provided expression. This is used in calls to `map`.
|
||||
*/
|
||||
function expressionToStatement(expression: Expression) {
|
||||
return createStatement(expression, /*location*/ undefined);
|
||||
return createStatement(expression);
|
||||
}
|
||||
|
||||
function addExportMemberAssignment(statements: Statement[], node: ClassDeclaration | FunctionDeclaration) {
|
||||
@@ -3052,17 +3091,19 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createNamespaceExport(exportName: Identifier, exportValue: Expression, location?: TextRange) {
|
||||
return createStatement(
|
||||
createAssignment(
|
||||
getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true),
|
||||
exportValue
|
||||
return setTextRange(
|
||||
createStatement(
|
||||
createAssignment(
|
||||
getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true),
|
||||
exportValue
|
||||
)
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
function createNamespaceExportExpression(exportName: Identifier, exportValue: Expression, location?: TextRange) {
|
||||
return createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue, location);
|
||||
return setTextRange(createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue), location);
|
||||
}
|
||||
|
||||
function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name: Identifier) {
|
||||
@@ -3094,7 +3135,7 @@ namespace ts {
|
||||
function getClassAliasIfNeeded(node: ClassDeclaration) {
|
||||
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) {
|
||||
enableSubstitutionForClassAliases();
|
||||
const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? node.name.text : "default");
|
||||
const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? unescapeIdentifier(node.name.text) : "default");
|
||||
classAliases[getOriginalNodeId(node)] = classAlias;
|
||||
hoistVariableDeclaration(classAlias);
|
||||
return classAlias;
|
||||
@@ -3156,12 +3197,17 @@ namespace ts {
|
||||
/**
|
||||
* Hook for node emit.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to emit.
|
||||
* @param emit A callback used to emit the node in the printer.
|
||||
*/
|
||||
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
|
||||
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
|
||||
const savedApplicableSubstitutions = applicableSubstitutions;
|
||||
const savedCurrentSourceFile = currentSourceFile;
|
||||
|
||||
if (isSourceFile(node)) {
|
||||
currentSourceFile = node;
|
||||
}
|
||||
|
||||
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isTransformedModuleDeclaration(node)) {
|
||||
applicableSubstitutions |= TypeScriptSubstitutionFlags.NamespaceExports;
|
||||
@@ -3171,20 +3217,21 @@ namespace ts {
|
||||
applicableSubstitutions |= TypeScriptSubstitutionFlags.NonQualifiedEnumMembers;
|
||||
}
|
||||
|
||||
previousOnEmitNode(emitContext, node, emitCallback);
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
|
||||
applicableSubstitutions = savedApplicableSubstitutions;
|
||||
currentSourceFile = savedCurrentSourceFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks node substitutions.
|
||||
*
|
||||
* @param emitContext A context hint for the emitter.
|
||||
* @param hint A hint as to the intended usage of the node.
|
||||
* @param node The node to substitute.
|
||||
*/
|
||||
function onSubstituteNode(emitContext: EmitContext, node: Node) {
|
||||
node = previousOnSubstituteNode(emitContext, node);
|
||||
if (emitContext === EmitContext.Expression) {
|
||||
function onSubstituteNode(hint: EmitHint, node: Node) {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (hint === EmitHint.Expression) {
|
||||
return substituteExpression(<Expression>node);
|
||||
}
|
||||
else if (isShorthandPropertyAssignment(node)) {
|
||||
@@ -3203,9 +3250,9 @@ namespace ts {
|
||||
// destructuring assignment
|
||||
if (node.objectAssignmentInitializer) {
|
||||
const initializer = createAssignment(exportedName, node.objectAssignmentInitializer);
|
||||
return createPropertyAssignment(name, initializer, /*location*/ node);
|
||||
return setTextRange(createPropertyAssignment(name, initializer), node);
|
||||
}
|
||||
return createPropertyAssignment(name, exportedName, /*location*/ node);
|
||||
return setTextRange(createPropertyAssignment(name, exportedName), node);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
@@ -3265,7 +3312,10 @@ namespace ts {
|
||||
(applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) ||
|
||||
(applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration);
|
||||
if (substitute) {
|
||||
return createPropertyAccess(getGeneratedNameForNode(container), node, /*location*/ node);
|
||||
return setTextRange(
|
||||
createPropertyAccess(getGeneratedNameForNode(container), node),
|
||||
/*location*/ node
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3284,17 +3334,18 @@ namespace ts {
|
||||
function substituteConstantValue(node: PropertyAccessExpression | ElementAccessExpression): LeftHandSideExpression {
|
||||
const constantValue = tryGetConstEnumValue(node);
|
||||
if (constantValue !== undefined) {
|
||||
// track the constant value on the node for the printer in needsDotDotForPropertyAccess
|
||||
setConstantValue(node, constantValue);
|
||||
|
||||
const substitute = createLiteral(constantValue);
|
||||
setSourceMapRange(substitute, node);
|
||||
setCommentRange(substitute, node);
|
||||
if (!compilerOptions.removeComments) {
|
||||
const propertyName = isPropertyAccessExpression(node)
|
||||
? declarationNameToString(node.name)
|
||||
: getTextOfNode(node.argumentExpression);
|
||||
substitute.trailingComment = ` ${propertyName} `;
|
||||
|
||||
addSyntheticTrailingComment(substitute, SyntaxKind.MultiLineCommentTrivia, ` ${propertyName} `);
|
||||
}
|
||||
|
||||
setConstantValue(node, constantValue);
|
||||
return substitute;
|
||||
}
|
||||
|
||||
@@ -3312,51 +3363,28 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const paramHelper: EmitHelper = {
|
||||
name: "typescript:param",
|
||||
scoped: false,
|
||||
priority: 4,
|
||||
text: `
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};`
|
||||
};
|
||||
function createDecorateHelper(context: TransformationContext, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
|
||||
const argumentsArray: Expression[] = [];
|
||||
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*multiLine*/ true));
|
||||
argumentsArray.push(target);
|
||||
if (memberName) {
|
||||
argumentsArray.push(memberName);
|
||||
if (descriptor) {
|
||||
argumentsArray.push(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
function createParamHelper(context: TransformationContext, expression: Expression, parameterOffset: number, location?: TextRange) {
|
||||
context.requestEmitHelper(paramHelper);
|
||||
return createCall(
|
||||
getHelperName("__param"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(parameterOffset),
|
||||
expression
|
||||
],
|
||||
context.requestEmitHelper(decorateHelper);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__decorate"),
|
||||
/*typeArguments*/ undefined,
|
||||
argumentsArray
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
const metadataHelper: EmitHelper = {
|
||||
name: "typescript:metadata",
|
||||
scoped: false,
|
||||
priority: 3,
|
||||
text: `
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};`
|
||||
};
|
||||
|
||||
function createMetadataHelper(context: TransformationContext, metadataKey: string, metadataValue: Expression) {
|
||||
context.requestEmitHelper(metadataHelper);
|
||||
return createCall(
|
||||
getHelperName("__metadata"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(metadataKey),
|
||||
metadataValue
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
const decorateHelper: EmitHelper = {
|
||||
name: "typescript:decorate",
|
||||
scoped: false,
|
||||
@@ -3370,18 +3398,50 @@ namespace ts {
|
||||
};`
|
||||
};
|
||||
|
||||
function createDecorateHelper(context: TransformationContext, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
|
||||
context.requestEmitHelper(decorateHelper);
|
||||
const argumentsArray: Expression[] = [];
|
||||
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true));
|
||||
argumentsArray.push(target);
|
||||
if (memberName) {
|
||||
argumentsArray.push(memberName);
|
||||
if (descriptor) {
|
||||
argumentsArray.push(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return createCall(getHelperName("__decorate"), /*typeArguments*/ undefined, argumentsArray, location);
|
||||
function createMetadataHelper(context: TransformationContext, metadataKey: string, metadataValue: Expression) {
|
||||
context.requestEmitHelper(metadataHelper);
|
||||
return createCall(
|
||||
getHelperName("__metadata"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(metadataKey),
|
||||
metadataValue
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
const metadataHelper: EmitHelper = {
|
||||
name: "typescript:metadata",
|
||||
scoped: false,
|
||||
priority: 3,
|
||||
text: `
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};`
|
||||
};
|
||||
|
||||
function createParamHelper(context: TransformationContext, expression: Expression, parameterOffset: number, location?: TextRange) {
|
||||
context.requestEmitHelper(paramHelper);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__param"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(parameterOffset),
|
||||
expression
|
||||
]
|
||||
),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
const paramHelper: EmitHelper = {
|
||||
name: "typescript:param",
|
||||
scoped: false,
|
||||
priority: 4,
|
||||
text: `
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};`
|
||||
};
|
||||
}
|
||||
|
||||
+10
-9
@@ -1,4 +1,4 @@
|
||||
/// <reference path="program.ts"/>
|
||||
/// <reference path="program.ts"/>
|
||||
/// <reference path="commandLineParser.ts"/>
|
||||
|
||||
namespace ts {
|
||||
@@ -225,9 +225,9 @@ namespace ts {
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
if (commandLine.options.help) {
|
||||
if (commandLine.options.help || commandLine.options.all) {
|
||||
printVersion();
|
||||
printHelp();
|
||||
printHelp(commandLine.options.all);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace ts {
|
||||
|
||||
if (commandLine.fileNames.length === 0 && !configFileName) {
|
||||
printVersion();
|
||||
printHelp();
|
||||
printHelp(commandLine.options.all);
|
||||
return sys.exit(ExitStatus.Success);
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ namespace ts {
|
||||
// is an absolute file name.
|
||||
directory == "" ? "." : directory,
|
||||
watchedDirectoryChanged, /*recursive*/ true);
|
||||
};
|
||||
}
|
||||
}
|
||||
return configParseResult;
|
||||
}
|
||||
@@ -618,7 +618,7 @@ namespace ts {
|
||||
sys.write(getDiagnosticText(Diagnostics.Version_0, ts.version) + sys.newLine);
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
function printHelp(showAllOptions: boolean) {
|
||||
const output: string[] = [];
|
||||
|
||||
// We want to align our "syntax" and "examples" commands to a certain margin.
|
||||
@@ -643,8 +643,9 @@ namespace ts {
|
||||
output.push(getDiagnosticText(Diagnostics.Options_Colon) + sys.newLine);
|
||||
|
||||
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
|
||||
const optsList = filter(optionDeclarations.slice(), v => !v.experimental);
|
||||
optsList.sort((a, b) => compareValues<string>(a.name.toLowerCase(), b.name.toLowerCase()));
|
||||
const optsList = showAllOptions ?
|
||||
optionDeclarations.slice().sort((a, b) => compareValues<string>(a.name.toLowerCase(), b.name.toLowerCase())) :
|
||||
filter(optionDeclarations.slice(), v => v.showInSimplifiedHelpView);
|
||||
|
||||
// We want our descriptions to align at the same column in our output,
|
||||
// so we keep track of the longest option usage string.
|
||||
@@ -738,7 +739,7 @@ namespace ts {
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined);
|
||||
}
|
||||
else {
|
||||
sys.writeFile(file, JSON.stringify(generateTSConfig(options, fileNames), undefined, 4));
|
||||
sys.writeFile(file, generateTSConfig(options, fileNames, sys.newLine));
|
||||
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined);
|
||||
}
|
||||
|
||||
|
||||
+507
-171
File diff suppressed because it is too large
Load Diff
+336
-301
@@ -1,4 +1,4 @@
|
||||
/// <reference path="sys.ts" />
|
||||
/// <reference path="sys.ts" />
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
@@ -24,6 +24,20 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function findDeclaration<T extends Declaration>(symbol: Symbol, predicate: (node: Declaration) => node is T): T | undefined;
|
||||
export function findDeclaration(symbol: Symbol, predicate: (node: Declaration) => boolean): Declaration | undefined;
|
||||
export function findDeclaration(symbol: Symbol, predicate: (node: Declaration) => boolean): Declaration | undefined {
|
||||
const declarations = symbol.declarations;
|
||||
if (declarations) {
|
||||
for (const declaration of declarations) {
|
||||
if (predicate(declaration)) {
|
||||
return declaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export interface StringSymbolWriter extends SymbolWriter {
|
||||
string(): string;
|
||||
}
|
||||
@@ -53,7 +67,8 @@ namespace ts {
|
||||
decreaseIndent: noop,
|
||||
clear: () => str = "",
|
||||
trackSymbol: noop,
|
||||
reportInaccessibleThisError: noop
|
||||
reportInaccessibleThisError: noop,
|
||||
reportIllegalExtends: noop
|
||||
};
|
||||
}
|
||||
|
||||
@@ -169,7 +184,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getStartPositionOfLine(line: number, sourceFile: SourceFile): number {
|
||||
export function getStartPositionOfLine(line: number, sourceFile: SourceFileLike): number {
|
||||
Debug.assert(line >= 0);
|
||||
return getLineStarts(sourceFile)[line];
|
||||
}
|
||||
@@ -189,7 +204,7 @@ namespace ts {
|
||||
return value !== undefined;
|
||||
}
|
||||
|
||||
export function getEndLinePosition(line: number, sourceFile: SourceFile): number {
|
||||
export function getEndLinePosition(line: number, sourceFile: SourceFileLike): number {
|
||||
Debug.assert(line >= 0);
|
||||
const lineStarts = getLineStarts(sourceFile);
|
||||
|
||||
@@ -240,7 +255,11 @@ namespace ts {
|
||||
return !nodeIsMissing(node);
|
||||
}
|
||||
|
||||
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile, includeJsDoc?: boolean): number {
|
||||
export function isToken(n: Node): boolean {
|
||||
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
|
||||
}
|
||||
|
||||
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, includeJsDoc?: boolean): number {
|
||||
// With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
|
||||
// want to skip trivia because this will launch us forward to the next token.
|
||||
if (nodeIsMissing(node)) {
|
||||
@@ -274,7 +293,7 @@ namespace ts {
|
||||
return node.kind >= SyntaxKind.FirstJSDocTagNode && node.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
}
|
||||
|
||||
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
|
||||
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFileLike): number {
|
||||
if (nodeIsMissing(node) || !node.decorators) {
|
||||
return getTokenPosOfNode(node, sourceFile);
|
||||
}
|
||||
@@ -303,21 +322,11 @@ namespace ts {
|
||||
return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node, includeTrivia);
|
||||
}
|
||||
|
||||
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, languageVersion: ScriptTarget) {
|
||||
// Any template literal or string literal with an extended escape
|
||||
// (e.g. "\u{0067}") will need to be downleveled as a escaped string literal.
|
||||
if (languageVersion < ScriptTarget.ES2015 && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) {
|
||||
return getQuotedEscapedLiteralText('"', node.text, '"');
|
||||
}
|
||||
|
||||
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile) {
|
||||
// If we don't need to downlevel and we can reach the original source text using
|
||||
// the node's parent reference, then simply get the text as it was originally written.
|
||||
if (!nodeIsSynthesized(node) && node.parent) {
|
||||
const text = getSourceTextOfNodeFromSourceFile(sourceFile, node);
|
||||
if (languageVersion < ScriptTarget.ES2015 && isBinaryOrOctalIntegerLiteral(node, text)) {
|
||||
return node.text;
|
||||
}
|
||||
return text;
|
||||
return getSourceTextOfNodeFromSourceFile(sourceFile, node);
|
||||
}
|
||||
|
||||
// If we can't reach the original source text, use the canonical form if it's a number,
|
||||
@@ -340,19 +349,6 @@ namespace ts {
|
||||
Debug.fail(`Literal kind '${node.kind}' not accounted for.`);
|
||||
}
|
||||
|
||||
export function isBinaryOrOctalIntegerLiteral(node: LiteralLikeNode, text: string) {
|
||||
if (node.kind === SyntaxKind.NumericLiteral && text.length > 1) {
|
||||
switch (text.charCodeAt(1)) {
|
||||
case CharacterCodes.b:
|
||||
case CharacterCodes.B:
|
||||
case CharacterCodes.o:
|
||||
case CharacterCodes.O:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getQuotedEscapedLiteralText(leftQuote: string, text: string, rightQuote: string) {
|
||||
return leftQuote + escapeNonAsciiCharacters(escapeString(text)) + rightQuote;
|
||||
}
|
||||
@@ -362,11 +358,6 @@ namespace ts {
|
||||
return identifier.length >= 2 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ ? "_" + identifier : identifier;
|
||||
}
|
||||
|
||||
// Remove extra underscore from escaped identifier
|
||||
export function unescapeIdentifier(identifier: string): string {
|
||||
return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier;
|
||||
}
|
||||
|
||||
// Make an identifier from an external module name by extracting the string after the last "/" and replacing
|
||||
// all non-alphanumeric characters with underscores
|
||||
export function makeIdentifierFromModuleName(moduleName: string): string {
|
||||
@@ -388,14 +379,14 @@ namespace ts {
|
||||
((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(<ModuleDeclaration>node));
|
||||
}
|
||||
|
||||
/** Given a symbol for a module, checks that it is either an untyped import or a shorthand ambient module. */
|
||||
/** Given a symbol for a module, checks that it is a shorthand ambient module. */
|
||||
export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean {
|
||||
return isShorthandAmbientModule(moduleSymbol.valueDeclaration);
|
||||
}
|
||||
|
||||
function isShorthandAmbientModule(node: Node): boolean {
|
||||
// The only kind of module that can be missing a body is a shorthand ambient module.
|
||||
return node.kind === SyntaxKind.ModuleDeclaration && (!(<ModuleDeclaration>node).body);
|
||||
return node && node.kind === SyntaxKind.ModuleDeclaration && (!(<ModuleDeclaration>node).body);
|
||||
}
|
||||
|
||||
export function isBlockScopedContainerTopLevel(node: Node): boolean {
|
||||
@@ -475,6 +466,10 @@ namespace ts {
|
||||
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
|
||||
}
|
||||
|
||||
export function getNameFromIndexInfo(info: IndexInfo) {
|
||||
return info.declaration ? declarationNameToString(info.declaration.parameters[0].name) : undefined;
|
||||
}
|
||||
|
||||
export function getTextOfPropertyName(name: PropertyName): string {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
@@ -690,8 +685,8 @@ namespace ts {
|
||||
//
|
||||
// let a: A.B.C;
|
||||
//
|
||||
// Calling isPartOfTypeNode would consider the qualified name A.B a type node. Only C or
|
||||
// A.B.C is a type node.
|
||||
// Calling isPartOfTypeNode would consider the qualified name A.B a type node.
|
||||
// Only C and A.B.C are type nodes.
|
||||
if (SyntaxKind.FirstTypeNode <= parent.kind && parent.kind <= SyntaxKind.LastTypeNode) {
|
||||
return true;
|
||||
}
|
||||
@@ -914,7 +909,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function unwrapInnermostStatmentOfLabel(node: LabeledStatement, beforeUnwrapLabelCallback?: (node: LabeledStatement) => void) {
|
||||
export function unwrapInnermostStatementOfLabel(node: LabeledStatement, beforeUnwrapLabelCallback?: (node: LabeledStatement) => void) {
|
||||
while (true) {
|
||||
if (beforeUnwrapLabelCallback) {
|
||||
beforeUnwrapLabelCallback(node);
|
||||
@@ -1041,13 +1036,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an super call/property node, returns the closest node where
|
||||
* - a super call/property access is legal in the node and not legal in the parent node the node.
|
||||
* i.e. super call is legal in constructor but not legal in the class body.
|
||||
* - the container is an arrow function (so caller might need to call getSuperContainer again in case it needs to climb higher)
|
||||
* - a super call/property is definitely illegal in the container (but might be legal in some subnode)
|
||||
* i.e. super property access is illegal in function declaration but can be legal in the statement list
|
||||
*/
|
||||
* Given an super call/property node, returns the closest node where
|
||||
* - a super call/property access is legal in the node and not legal in the parent node the node.
|
||||
* i.e. super call is legal in constructor but not legal in the class body.
|
||||
* - the container is an arrow function (so caller might need to call getSuperContainer again in case it needs to climb higher)
|
||||
* - a super call/property is definitely illegal in the container (but might be legal in some subnode)
|
||||
* i.e. super property access is illegal in function declaration but can be legal in the statement list
|
||||
*/
|
||||
export function getSuperContainer(node: Node, stopOnFunctions: boolean): Node {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
@@ -1133,6 +1128,8 @@ namespace ts {
|
||||
|
||||
export function isCallLikeExpression(node: Node): node is CallLikeExpression {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.CallExpression:
|
||||
case SyntaxKind.NewExpression:
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
@@ -1147,6 +1144,9 @@ namespace ts {
|
||||
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
return (<TaggedTemplateExpression>node).tag;
|
||||
}
|
||||
else if (isJsxOpeningLikeElement(node)) {
|
||||
return node.tagName;
|
||||
}
|
||||
|
||||
// Will either be a CallExpression, NewExpression, or Decorator.
|
||||
return (<CallExpression | Decorator>node).expression;
|
||||
@@ -1345,17 +1345,24 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Returns true if the node is a CallExpression to the identifier 'require' with
|
||||
* exactly one argument.
|
||||
* exactly one argument (of the form 'require("name")').
|
||||
* This function does not test if the node is in a JavaScript file or not.
|
||||
*/
|
||||
export function isRequireCall(expression: Node, checkArgumentIsStringLiteral: boolean): expression is CallExpression {
|
||||
// of the form 'require("name")'
|
||||
const isRequire = expression.kind === SyntaxKind.CallExpression &&
|
||||
(<CallExpression>expression).expression.kind === SyntaxKind.Identifier &&
|
||||
(<Identifier>(<CallExpression>expression).expression).text === "require" &&
|
||||
(<CallExpression>expression).arguments.length === 1;
|
||||
*/
|
||||
export function isRequireCall(callExpression: Node, checkArgumentIsStringLiteral: boolean): callExpression is CallExpression {
|
||||
if (callExpression.kind !== SyntaxKind.CallExpression) {
|
||||
return false;
|
||||
}
|
||||
const { expression, arguments: args } = callExpression as CallExpression;
|
||||
|
||||
return isRequire && (!checkArgumentIsStringLiteral || (<CallExpression>expression).arguments[0].kind === SyntaxKind.StringLiteral);
|
||||
if (expression.kind !== SyntaxKind.Identifier || (expression as Identifier).text !== "require") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.length !== 1) {
|
||||
return false;
|
||||
}
|
||||
const arg = args[0];
|
||||
return !checkArgumentIsStringLiteral || arg.kind === SyntaxKind.StringLiteral || arg.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
|
||||
}
|
||||
|
||||
export function isSingleOrDoubleQuote(charCode: number) {
|
||||
@@ -1366,23 +1373,35 @@ namespace ts {
|
||||
* Returns true if the node is a variable declaration whose initializer is a function expression.
|
||||
* This function does not test if the node is in a JavaScript file or not.
|
||||
*/
|
||||
export function isDeclarationOfFunctionExpression(s: Symbol) {
|
||||
export function isDeclarationOfFunctionOrClassExpression(s: Symbol) {
|
||||
if (s.valueDeclaration && s.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
|
||||
const declaration = s.valueDeclaration as VariableDeclaration;
|
||||
return declaration.initializer && declaration.initializer.kind === SyntaxKind.FunctionExpression;
|
||||
return declaration.initializer && (declaration.initializer.kind === SyntaxKind.FunctionExpression || declaration.initializer.kind === SyntaxKind.ClassExpression);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getRightMostAssignedExpression(node: Node) {
|
||||
while (isAssignmentExpression(node, /*excludeCompoundAssignements*/ true)) {
|
||||
node = node.right;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
export function isExportsIdentifier(node: Node) {
|
||||
return isIdentifier(node) && node.text === "exports";
|
||||
}
|
||||
|
||||
export function isModuleExportsPropertyAccessExpression(node: Node) {
|
||||
return isPropertyAccessExpression(node) && isIdentifier(node.expression) && node.expression.text === "module" && node.name.text === "exports";
|
||||
}
|
||||
|
||||
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
|
||||
/// assignments we treat as special in the binder
|
||||
export function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind {
|
||||
export function getSpecialPropertyAssignmentKind(expression: ts.BinaryExpression): SpecialPropertyAssignmentKind {
|
||||
if (!isInJavaScriptFile(expression)) {
|
||||
return SpecialPropertyAssignmentKind.None;
|
||||
}
|
||||
if (expression.kind !== SyntaxKind.BinaryExpression) {
|
||||
return SpecialPropertyAssignmentKind.None;
|
||||
}
|
||||
const expr = <BinaryExpression>expression;
|
||||
if (expr.operatorToken.kind !== SyntaxKind.EqualsToken || expr.left.kind !== SyntaxKind.PropertyAccessExpression) {
|
||||
return SpecialPropertyAssignmentKind.None;
|
||||
@@ -1398,6 +1417,10 @@ namespace ts {
|
||||
// module.exports = expr
|
||||
return SpecialPropertyAssignmentKind.ModuleExports;
|
||||
}
|
||||
else {
|
||||
// F.x = expr
|
||||
return SpecialPropertyAssignmentKind.Property;
|
||||
}
|
||||
}
|
||||
else if (lhs.expression.kind === SyntaxKind.ThisKeyword) {
|
||||
return SpecialPropertyAssignmentKind.ThisProperty;
|
||||
@@ -1417,6 +1440,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return SpecialPropertyAssignmentKind.None;
|
||||
}
|
||||
|
||||
@@ -1482,6 +1506,11 @@ namespace ts {
|
||||
return map(getJSDocs(node), doc => doc.comment);
|
||||
}
|
||||
|
||||
export function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration) {
|
||||
const parameterTags = getJSDocTags(node, SyntaxKind.JSDocParameterTag);
|
||||
return parameterTags && parameterTags.length > 0;
|
||||
}
|
||||
|
||||
function getJSDocTags(node: Node, kind: SyntaxKind): JSDocTag[] {
|
||||
const docs = getJSDocs(node);
|
||||
if (docs) {
|
||||
@@ -1493,7 +1522,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.push(...filter((doc as JSDoc).tags, tag => tag.kind === kind));
|
||||
const tags = (doc as JSDoc).tags;
|
||||
if (tags) {
|
||||
result.push(...filter(tags, tag => tag.kind === kind));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -1504,7 +1536,7 @@ namespace ts {
|
||||
return node && firstOrUndefined(getJSDocTags(node, kind));
|
||||
}
|
||||
|
||||
function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
|
||||
export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
|
||||
let cache: (JSDoc | JSDocTag)[] = node.jsDocCache;
|
||||
if (!cache) {
|
||||
getJSDocsWorker(node);
|
||||
@@ -1662,11 +1694,15 @@ namespace ts {
|
||||
node = parent;
|
||||
break;
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
if ((<ShorthandPropertyAssignment>parent).name !== node) {
|
||||
if ((parent as ShorthandPropertyAssignment).name !== node) {
|
||||
return AssignmentKind.None;
|
||||
}
|
||||
// Fall through
|
||||
node = parent.parent;
|
||||
break;
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
if ((parent as ShorthandPropertyAssignment).name === node) {
|
||||
return AssignmentKind.None;
|
||||
}
|
||||
node = parent.parent;
|
||||
break;
|
||||
default:
|
||||
@@ -1678,7 +1714,8 @@ namespace ts {
|
||||
|
||||
// A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property
|
||||
// assignment in an object literal that is an assignment target, or if it is parented by an array literal that is
|
||||
// an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ p: a}] = xxx'.
|
||||
// an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ a }] = xxx'.
|
||||
// (Note that `p` is not a target in the above examples, only `a`.)
|
||||
export function isAssignmentTarget(node: Node): boolean {
|
||||
return getAssignmentTargetKind(node) !== AssignmentKind.None;
|
||||
}
|
||||
@@ -1884,8 +1921,55 @@ namespace ts {
|
||||
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
|
||||
}
|
||||
|
||||
export function isAsyncFunctionLike(node: Node): boolean {
|
||||
return isFunctionLike(node) && hasModifier(node, ModifierFlags.Async) && !isAccessor(node);
|
||||
export const enum FunctionFlags {
|
||||
Normal = 0,
|
||||
Generator = 1 << 0,
|
||||
Async = 1 << 1,
|
||||
AsyncOrAsyncGenerator = Async | Generator,
|
||||
Invalid = 1 << 2,
|
||||
InvalidAsyncOrAsyncGenerator = AsyncOrAsyncGenerator | Invalid,
|
||||
InvalidGenerator = Generator | Invalid,
|
||||
}
|
||||
|
||||
export function getFunctionFlags(node: FunctionLikeDeclaration) {
|
||||
let flags = FunctionFlags.Normal;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
if (node.asteriskToken) {
|
||||
flags |= FunctionFlags.Generator;
|
||||
}
|
||||
// fall through
|
||||
case SyntaxKind.ArrowFunction:
|
||||
if (hasModifier(node, ModifierFlags.Async)) {
|
||||
flags |= FunctionFlags.Async;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!node.body) {
|
||||
flags |= FunctionFlags.Invalid;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
export function isAsyncFunction(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return (<FunctionLikeDeclaration>node).body !== undefined
|
||||
&& (<FunctionLikeDeclaration>node).asteriskToken === undefined
|
||||
&& hasModifier(node, ModifierFlags.Async);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isNumericLiteral(node: Node): node is NumericLiteral {
|
||||
return node.kind === SyntaxKind.NumericLiteral;
|
||||
}
|
||||
|
||||
export function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral {
|
||||
@@ -2001,67 +2085,19 @@ namespace ts {
|
||||
|| positionIsSynthesized(node.end);
|
||||
}
|
||||
|
||||
export function getOriginalNode(node: Node): Node;
|
||||
export function getOriginalNode<T extends Node>(node: Node, nodeTest: (node: Node) => node is T): T;
|
||||
export function getOriginalNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
|
||||
if (node) {
|
||||
while (node.original !== undefined) {
|
||||
node = node.original;
|
||||
}
|
||||
export function getOriginalSourceFileOrBundle(sourceFileOrBundle: SourceFile | Bundle) {
|
||||
if (sourceFileOrBundle.kind === SyntaxKind.Bundle) {
|
||||
return updateBundle(sourceFileOrBundle, sameMap(sourceFileOrBundle.sourceFiles, getOriginalSourceFile));
|
||||
}
|
||||
|
||||
return !nodeTest || nodeTest(node) ? node : undefined;
|
||||
return getOriginalSourceFile(sourceFileOrBundle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether a node originated in the parse tree.
|
||||
*
|
||||
* @param node The node to test.
|
||||
*/
|
||||
export function isParseTreeNode(node: Node): boolean {
|
||||
return (node.flags & NodeFlags.Synthesized) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the original parse tree node for a node.
|
||||
*
|
||||
* @param node The original node.
|
||||
* @returns The original parse tree node if found; otherwise, undefined.
|
||||
*/
|
||||
export function getParseTreeNode(node: Node): Node;
|
||||
|
||||
/**
|
||||
* Gets the original parse tree node for a node.
|
||||
*
|
||||
* @param node The original node.
|
||||
* @param nodeTest A callback used to ensure the correct type of parse tree node is returned.
|
||||
* @returns The original parse tree node if found; otherwise, undefined.
|
||||
*/
|
||||
export function getParseTreeNode<T extends Node>(node: Node, nodeTest?: (node: Node) => node is T): T;
|
||||
export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
|
||||
if (isParseTreeNode(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
node = getOriginalNode(node);
|
||||
|
||||
if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
function getOriginalSourceFile(sourceFile: SourceFile) {
|
||||
return getParseTreeNode(sourceFile, isSourceFile) || sourceFile;
|
||||
}
|
||||
|
||||
export function getOriginalSourceFiles(sourceFiles: SourceFile[]) {
|
||||
const originalSourceFiles: SourceFile[] = [];
|
||||
for (const sourceFile of sourceFiles) {
|
||||
const originalSourceFile = getParseTreeNode(sourceFile, isSourceFile);
|
||||
if (originalSourceFile) {
|
||||
originalSourceFiles.push(originalSourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
return originalSourceFiles;
|
||||
return sameMap(sourceFiles, getOriginalSourceFile);
|
||||
}
|
||||
|
||||
export function getOriginalNodeId(node: Node) {
|
||||
@@ -2400,23 +2436,6 @@ namespace ts {
|
||||
s;
|
||||
}
|
||||
|
||||
export interface EmitTextWriter {
|
||||
write(s: string): void;
|
||||
writeTextOfNode(text: string, node: Node): void;
|
||||
writeLine(): void;
|
||||
increaseIndent(): void;
|
||||
decreaseIndent(): void;
|
||||
getText(): string;
|
||||
rawWrite(s: string): void;
|
||||
writeLiteral(s: string): void;
|
||||
getTextPos(): number;
|
||||
getLine(): number;
|
||||
getColumn(): number;
|
||||
getIndent(): number;
|
||||
isAtStartOfLine(): boolean;
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
const indentStrings: string[] = ["", " "];
|
||||
export function getIndentString(level: number) {
|
||||
if (indentStrings[level] === undefined) {
|
||||
@@ -2429,7 +2448,7 @@ namespace ts {
|
||||
return indentStrings[1].length;
|
||||
}
|
||||
|
||||
export function createTextWriter(newLine: String): EmitTextWriter {
|
||||
export function createTextWriter(newLine: string): EmitTextWriter {
|
||||
let output: string;
|
||||
let indent: number;
|
||||
let lineStart: boolean;
|
||||
@@ -2568,102 +2587,57 @@ namespace ts {
|
||||
* @param host An EmitHost.
|
||||
* @param targetSourceFile An optional target source file to emit.
|
||||
*/
|
||||
export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile) {
|
||||
export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile): SourceFile[] {
|
||||
const options = host.getCompilerOptions();
|
||||
const isSourceFileFromExternalLibrary = (file: SourceFile) => host.isSourceFileFromExternalLibrary(file);
|
||||
if (options.outFile || options.out) {
|
||||
const moduleKind = getEmitModuleKind(options);
|
||||
const moduleEmitEnabled = moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.System;
|
||||
const sourceFiles = getAllEmittableSourceFiles();
|
||||
// Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified
|
||||
return filter(sourceFiles, moduleEmitEnabled ? isNonDeclarationFile : isBundleEmitNonExternalModule);
|
||||
return filter(host.getSourceFiles(), sourceFile =>
|
||||
(moduleEmitEnabled || !isExternalModule(sourceFile)) && sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary));
|
||||
}
|
||||
else {
|
||||
const sourceFiles = targetSourceFile === undefined ? getAllEmittableSourceFiles() : [targetSourceFile];
|
||||
return filterSourceFilesInDirectory(sourceFiles, file => host.isSourceFileFromExternalLibrary(file));
|
||||
}
|
||||
|
||||
function getAllEmittableSourceFiles() {
|
||||
return options.noEmitForJsFiles ? filter(host.getSourceFiles(), sourceFile => !isSourceFileJavaScript(sourceFile)) : host.getSourceFiles();
|
||||
const sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile];
|
||||
return filter(sourceFiles, sourceFile => sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary));
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't call this for `--outFile`, just for `--outDir` or plain emit. */
|
||||
export function filterSourceFilesInDirectory(sourceFiles: SourceFile[], isSourceFileFromExternalLibrary: (file: SourceFile) => boolean): SourceFile[] {
|
||||
return filter(sourceFiles, file => shouldEmitInDirectory(file, isSourceFileFromExternalLibrary));
|
||||
}
|
||||
|
||||
function isNonDeclarationFile(sourceFile: SourceFile) {
|
||||
return !isDeclarationFile(sourceFile);
|
||||
/** Don't call this for `--outFile`, just for `--outDir` or plain emit. `--outFile` needs additional checks. */
|
||||
export function sourceFileMayBeEmitted(sourceFile: SourceFile, options: CompilerOptions, isSourceFileFromExternalLibrary: (file: SourceFile) => boolean) {
|
||||
return !(options.noEmitForJsFiles && isSourceFileJavaScript(sourceFile)) && !isDeclarationFile(sourceFile) && !isSourceFileFromExternalLibrary(sourceFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a file should be emitted in a non-`--outFile` case.
|
||||
* Don't emit if source file is a declaration file, or was located under node_modules
|
||||
*/
|
||||
function shouldEmitInDirectory(sourceFile: SourceFile, isSourceFileFromExternalLibrary: (file: SourceFile) => boolean): boolean {
|
||||
return isNonDeclarationFile(sourceFile) && !isSourceFileFromExternalLibrary(sourceFile);
|
||||
}
|
||||
|
||||
function isBundleEmitNonExternalModule(sourceFile: SourceFile) {
|
||||
return isNonDeclarationFile(sourceFile) && !isExternalModule(sourceFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over each source file to emit. The source files are expected to have been
|
||||
* transformed for use by the pretty printer.
|
||||
*
|
||||
* Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support
|
||||
* transformations.
|
||||
* Iterates over the source files that are expected to have an emit output.
|
||||
*
|
||||
* @param host An EmitHost.
|
||||
* @param sourceFiles The transformed source files to emit.
|
||||
* @param action The action to execute.
|
||||
* @param sourceFilesOrTargetSourceFile
|
||||
* If an array, the full list of source files to emit.
|
||||
* Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit.
|
||||
*/
|
||||
export function forEachTransformedEmitFile(host: EmitHost, sourceFiles: SourceFile[],
|
||||
action: (jsFilePath: string, sourceMapFilePath: string, declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) => void,
|
||||
export function forEachEmittedFile(
|
||||
host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean) => void,
|
||||
sourceFilesOrTargetSourceFile?: SourceFile[] | SourceFile,
|
||||
emitOnlyDtsFiles?: boolean) {
|
||||
|
||||
const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile);
|
||||
const options = host.getCompilerOptions();
|
||||
// Emit on each source file
|
||||
if (options.outFile || options.out) {
|
||||
onBundledEmit(sourceFiles);
|
||||
}
|
||||
else {
|
||||
for (const sourceFile of sourceFiles) {
|
||||
// Don't emit if source file is a declaration file, or was located under node_modules
|
||||
if (!isDeclarationFile(sourceFile) && !host.isSourceFileFromExternalLibrary(sourceFile)) {
|
||||
onSingleFileEmit(host, sourceFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onSingleFileEmit(host: EmitHost, sourceFile: SourceFile) {
|
||||
// JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
|
||||
// So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
|
||||
// For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
|
||||
let extension = ".js";
|
||||
if (options.jsx === JsxEmit.Preserve) {
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
if (fileExtensionIs(sourceFile.fileName, ".jsx")) {
|
||||
extension = ".jsx";
|
||||
}
|
||||
}
|
||||
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
|
||||
// TypeScript source file preserving JSX syntax
|
||||
extension = ".jsx";
|
||||
}
|
||||
}
|
||||
const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension);
|
||||
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
|
||||
const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (options.declaration || emitOnlyDtsFiles) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
|
||||
action(jsFilePath, sourceMapFilePath, declarationFilePath, [sourceFile], /*isBundledEmit*/ false);
|
||||
}
|
||||
|
||||
function onBundledEmit(sourceFiles: SourceFile[]) {
|
||||
if (sourceFiles.length) {
|
||||
const jsFilePath = options.outFile || options.out;
|
||||
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
|
||||
const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined;
|
||||
action(jsFilePath, sourceMapFilePath, declarationFilePath, sourceFiles, /*isBundledEmit*/ true);
|
||||
const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : "";
|
||||
action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const sourceFile of sourceFiles) {
|
||||
const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options));
|
||||
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
|
||||
const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
|
||||
action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFile, emitOnlyDtsFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2672,77 +2646,22 @@ namespace ts {
|
||||
return options.sourceMap ? jsFilePath + ".map" : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the source files that are expected to have an emit output. This function
|
||||
* is used by the legacy emitter and the declaration emitter and should not be used by
|
||||
* the tree transforming emitter.
|
||||
*
|
||||
* @param host An EmitHost.
|
||||
* @param action The action to execute.
|
||||
* @param targetSourceFile An optional target source file to emit.
|
||||
*/
|
||||
export function forEachExpectedEmitFile(host: EmitHost,
|
||||
action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) => void,
|
||||
targetSourceFile?: SourceFile,
|
||||
emitOnlyDtsFiles?: boolean) {
|
||||
const options = host.getCompilerOptions();
|
||||
// Emit on each source file
|
||||
if (options.outFile || options.out) {
|
||||
onBundledEmit(host);
|
||||
}
|
||||
else {
|
||||
const sourceFiles = targetSourceFile === undefined ? getSourceFilesToEmit(host) : [targetSourceFile];
|
||||
for (const sourceFile of sourceFiles) {
|
||||
if (shouldEmitInDirectory(sourceFile, file => host.isSourceFileFromExternalLibrary(file))) {
|
||||
onSingleFileEmit(host, sourceFile);
|
||||
// JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
|
||||
// So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
|
||||
// For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
|
||||
function getOutputExtension(sourceFile: SourceFile, options: CompilerOptions): string {
|
||||
if (options.jsx === JsxEmit.Preserve) {
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
if (fileExtensionIs(sourceFile.fileName, ".jsx")) {
|
||||
return ".jsx";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onSingleFileEmit(host: EmitHost, sourceFile: SourceFile) {
|
||||
// JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
|
||||
// So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
|
||||
// For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
|
||||
let extension = ".js";
|
||||
if (options.jsx === JsxEmit.Preserve) {
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
if (fileExtensionIs(sourceFile.fileName, ".jsx")) {
|
||||
extension = ".jsx";
|
||||
}
|
||||
}
|
||||
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
|
||||
// TypeScript source file preserving JSX syntax
|
||||
extension = ".jsx";
|
||||
}
|
||||
}
|
||||
const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, extension);
|
||||
const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
|
||||
const emitFileNames: EmitFileNames = {
|
||||
jsFilePath,
|
||||
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
|
||||
declarationFilePath
|
||||
};
|
||||
action(emitFileNames, [sourceFile], /*isBundledEmit*/false, emitOnlyDtsFiles);
|
||||
}
|
||||
|
||||
function onBundledEmit(host: EmitHost) {
|
||||
// Can emit only sources that are not declaration file and are either non module code or module with
|
||||
// --module or --target es6 specified. Files included by searching under node_modules are also not emitted.
|
||||
const bundledSources = filter(getSourceFilesToEmit(host),
|
||||
sourceFile => !isDeclarationFile(sourceFile) &&
|
||||
!host.isSourceFileFromExternalLibrary(sourceFile) &&
|
||||
(!isExternalModule(sourceFile) ||
|
||||
!!getEmitModuleKind(options)));
|
||||
if (bundledSources.length) {
|
||||
const jsFilePath = options.outFile || options.out;
|
||||
const emitFileNames: EmitFileNames = {
|
||||
jsFilePath,
|
||||
sourceMapFilePath: getSourceMapFilePath(jsFilePath, options),
|
||||
declarationFilePath: options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined
|
||||
};
|
||||
action(emitFileNames, bundledSources, /*isBundledEmit*/true, emitOnlyDtsFiles);
|
||||
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
|
||||
// TypeScript source file preserving JSX syntax
|
||||
return ".jsx";
|
||||
}
|
||||
}
|
||||
return ".js";
|
||||
}
|
||||
|
||||
export function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) {
|
||||
@@ -3182,6 +3101,15 @@ namespace ts {
|
||||
return tryGetClassExtendingExpressionWithTypeArguments(node) !== undefined;
|
||||
}
|
||||
|
||||
export function isExpressionWithTypeArgumentsInClassImplementsClause(node: Node): node is ExpressionWithTypeArguments {
|
||||
return node.kind === SyntaxKind.ExpressionWithTypeArguments
|
||||
&& isEntityNameExpression((node as ExpressionWithTypeArguments).expression)
|
||||
&& node.parent
|
||||
&& (<HeritageClause>node.parent).token === SyntaxKind.ImplementsKeyword
|
||||
&& node.parent.parent
|
||||
&& isClassLike(node.parent.parent);
|
||||
}
|
||||
|
||||
export function isEntityNameExpression(node: Expression): node is EntityNameExpression {
|
||||
return node.kind === SyntaxKind.Identifier ||
|
||||
node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((<PropertyAccessExpression>node).expression);
|
||||
@@ -3192,19 +3120,22 @@ namespace ts {
|
||||
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node);
|
||||
}
|
||||
|
||||
export function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean {
|
||||
const kind = expression.kind;
|
||||
if (kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
return (<ObjectLiteralExpression>expression).properties.length === 0;
|
||||
}
|
||||
if (kind === SyntaxKind.ArrayLiteralExpression) {
|
||||
return (<ArrayLiteralExpression>expression).elements.length === 0;
|
||||
}
|
||||
return false;
|
||||
export function isEmptyObjectLiteral(expression: Node): boolean {
|
||||
return expression.kind === SyntaxKind.ObjectLiteralExpression &&
|
||||
(<ObjectLiteralExpression>expression).properties.length === 0;
|
||||
}
|
||||
|
||||
export function isEmptyArrayLiteral(expression: Node): boolean {
|
||||
return expression.kind === SyntaxKind.ArrayLiteralExpression &&
|
||||
(<ArrayLiteralExpression>expression).elements.length === 0;
|
||||
}
|
||||
|
||||
export function getLocalSymbolForExportDefault(symbol: Symbol) {
|
||||
return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, ModifierFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined;
|
||||
return isExportDefaultSymbol(symbol) ? symbol.valueDeclaration.localSymbol : undefined;
|
||||
}
|
||||
|
||||
function isExportDefaultSymbol(symbol: Symbol): boolean {
|
||||
return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, ModifierFlags.Default);
|
||||
}
|
||||
|
||||
/** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */
|
||||
@@ -3289,7 +3220,7 @@ namespace ts {
|
||||
|
||||
const carriageReturnLineFeed = "\r\n";
|
||||
const lineFeed = "\n";
|
||||
export function getNewLineCharacter(options: CompilerOptions): string {
|
||||
export function getNewLineCharacter(options: CompilerOptions | PrinterOptions): string {
|
||||
if (options.newLine === NewLineKind.CarriageReturnLineFeed) {
|
||||
return carriageReturnLineFeed;
|
||||
}
|
||||
@@ -3400,6 +3331,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function getRangePos(range: TextRange | undefined) {
|
||||
return range ? range.pos : -1;
|
||||
}
|
||||
|
||||
export function getRangeEnd(range: TextRange | undefined) {
|
||||
return range ? range.end : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases (or decreases) a position by the provided amount.
|
||||
*
|
||||
@@ -3727,10 +3666,14 @@ namespace ts {
|
||||
return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode)
|
||||
|| kind === SyntaxKind.AnyKeyword
|
||||
|| kind === SyntaxKind.NumberKeyword
|
||||
|| kind === SyntaxKind.ObjectKeyword
|
||||
|| kind === SyntaxKind.BooleanKeyword
|
||||
|| kind === SyntaxKind.StringKeyword
|
||||
|| kind === SyntaxKind.SymbolKeyword
|
||||
|| kind === SyntaxKind.ThisKeyword
|
||||
|| kind === SyntaxKind.VoidKeyword
|
||||
|| kind === SyntaxKind.UndefinedKeyword
|
||||
|| kind === SyntaxKind.NullKeyword
|
||||
|| kind === SyntaxKind.NeverKeyword
|
||||
|| kind === SyntaxKind.ExpressionWithTypeArguments;
|
||||
}
|
||||
@@ -3843,6 +3786,12 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.PropertyAccessExpression;
|
||||
}
|
||||
|
||||
export function isPropertyAccessOrQualifiedName(node: Node): node is PropertyAccessExpression | QualifiedName {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.PropertyAccessExpression
|
||||
|| kind === SyntaxKind.QualifiedName;
|
||||
}
|
||||
|
||||
export function isElementAccessExpression(node: Node): node is ElementAccessExpression {
|
||||
return node.kind === SyntaxKind.ElementAccessExpression;
|
||||
}
|
||||
@@ -3999,6 +3948,19 @@ namespace ts {
|
||||
export function isModuleBody(node: Node): node is ModuleBody {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ModuleBlock
|
||||
|| kind === SyntaxKind.ModuleDeclaration
|
||||
|| kind === SyntaxKind.Identifier;
|
||||
}
|
||||
|
||||
export function isNamespaceBody(node: Node): node is NamespaceBody {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ModuleBlock
|
||||
|| kind === SyntaxKind.ModuleDeclaration;
|
||||
}
|
||||
|
||||
export function isJSDocNamespaceBody(node: Node): node is JSDocNamespaceBody {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.Identifier
|
||||
|| kind === SyntaxKind.ModuleDeclaration;
|
||||
}
|
||||
|
||||
@@ -4048,6 +4010,7 @@ namespace ts {
|
||||
|| kind === SyntaxKind.ImportEqualsDeclaration
|
||||
|| kind === SyntaxKind.ImportSpecifier
|
||||
|| kind === SyntaxKind.InterfaceDeclaration
|
||||
|| kind === SyntaxKind.JsxAttribute
|
||||
|| kind === SyntaxKind.MethodDeclaration
|
||||
|| kind === SyntaxKind.MethodSignature
|
||||
|| kind === SyntaxKind.ModuleDeclaration
|
||||
@@ -4160,6 +4123,11 @@ namespace ts {
|
||||
|| kind === SyntaxKind.JsxText;
|
||||
}
|
||||
|
||||
export function isJsxAttributes(node: Node): node is JsxAttributes {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.JsxAttributes;
|
||||
}
|
||||
|
||||
export function isJsxAttributeLike(node: Node): node is JsxAttributeLike {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.JsxAttribute
|
||||
@@ -4180,6 +4148,12 @@ namespace ts {
|
||||
|| kind === SyntaxKind.JsxExpression;
|
||||
}
|
||||
|
||||
export function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.JsxOpeningElement
|
||||
|| kind === SyntaxKind.JsxSelfClosingElement;
|
||||
}
|
||||
|
||||
// Clauses
|
||||
|
||||
export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause {
|
||||
@@ -4228,13 +4202,13 @@ namespace ts {
|
||||
export function getDefaultLibFileName(options: CompilerOptions): string {
|
||||
switch (options.target) {
|
||||
case ScriptTarget.ESNext:
|
||||
return "lib.esnext.full.d.ts";
|
||||
case ScriptTarget.ES2017:
|
||||
return "lib.es2017.d.ts";
|
||||
return "lib.es2017.full.d.ts";
|
||||
case ScriptTarget.ES2016:
|
||||
return "lib.es2016.d.ts";
|
||||
return "lib.es2016.full.d.ts";
|
||||
case ScriptTarget.ES2015:
|
||||
return "lib.es6.d.ts";
|
||||
|
||||
return "lib.es6.d.ts"; // We don't use lib.es2015.full.d.ts due to breaking change.
|
||||
default:
|
||||
return "lib.d.ts";
|
||||
}
|
||||
@@ -4526,9 +4500,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the locale is in the appropriate format,
|
||||
* and if it is, attempts to set the appropriate language.
|
||||
*/
|
||||
* Checks to see if the locale is in the appropriate format,
|
||||
* and if it is, attempts to set the appropriate language.
|
||||
*/
|
||||
export function validateLocaleAndSetLanguage(
|
||||
locale: string,
|
||||
sys: { getExecutingFilePath(): string, resolvePath(path: string): string, fileExists(fileName: string): boolean, readFile(fileName: string): string },
|
||||
@@ -4591,4 +4565,65 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export function getOriginalNode(node: Node): Node;
|
||||
export function getOriginalNode<T extends Node>(node: Node, nodeTest: (node: Node) => node is T): T;
|
||||
export function getOriginalNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
|
||||
if (node) {
|
||||
while (node.original !== undefined) {
|
||||
node = node.original;
|
||||
}
|
||||
}
|
||||
|
||||
return !nodeTest || nodeTest(node) ? node : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether a node originated in the parse tree.
|
||||
*
|
||||
* @param node The node to test.
|
||||
*/
|
||||
export function isParseTreeNode(node: Node): boolean {
|
||||
return (node.flags & NodeFlags.Synthesized) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the original parse tree node for a node.
|
||||
*
|
||||
* @param node The original node.
|
||||
* @returns The original parse tree node if found; otherwise, undefined.
|
||||
*/
|
||||
export function getParseTreeNode(node: Node): Node;
|
||||
|
||||
/**
|
||||
* Gets the original parse tree node for a node.
|
||||
*
|
||||
* @param node The original node.
|
||||
* @param nodeTest A callback used to ensure the correct type of parse tree node is returned.
|
||||
* @returns The original parse tree node if found; otherwise, undefined.
|
||||
*/
|
||||
export function getParseTreeNode<T extends Node>(node: Node, nodeTest?: (node: Node) => node is T): T;
|
||||
export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
|
||||
if (node == undefined || isParseTreeNode(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
node = getOriginalNode(node);
|
||||
|
||||
if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove extra underscore from escaped identifier text content.
|
||||
*
|
||||
* @param identifier The escaped identifier text.
|
||||
* @returns The unescaped identifier text.
|
||||
*/
|
||||
export function unescapeIdentifier(identifier: string): string {
|
||||
return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier;
|
||||
}
|
||||
}
|
||||
|
||||
+912
-809
File diff suppressed because it is too large
Load Diff
@@ -51,7 +51,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
const path = ts.toPath(name, root, (fileName) => Harness.Compiler.getCanonicalFileName(fileName));
|
||||
const pathStart = ts.toPath(Harness.IO.getCurrentDirectory(), "", (fileName) => Harness.Compiler.getCanonicalFileName(fileName));
|
||||
return pathStart ? path.replace(pathStart, "/") : path;
|
||||
};
|
||||
}
|
||||
|
||||
public checkTestCodeOutput(fileName: string) {
|
||||
describe("compiler tests for " + fileName, () => {
|
||||
|
||||
+465
-115
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -22,6 +22,10 @@
|
||||
namespace FourSlash {
|
||||
ts.disableIncrementalParsing = false;
|
||||
|
||||
function normalizeNewLines(s: string) {
|
||||
return s.replace(/\r\n/g, "\n");
|
||||
}
|
||||
|
||||
// Represents a parsed source file with metadata
|
||||
export interface FourSlashFile {
|
||||
// The contents of the file (with markers, etc stripped out)
|
||||
@@ -183,7 +187,7 @@ namespace FourSlash {
|
||||
|
||||
// The current caret position in the active file
|
||||
public currentCaretPosition = 0;
|
||||
public lastKnownMarker: string = "";
|
||||
public lastKnownMarker = "";
|
||||
|
||||
// The file that's currently 'opened'
|
||||
public activeFile: FourSlashFile;
|
||||
@@ -263,6 +267,20 @@ namespace FourSlash {
|
||||
// Create map between fileName and its content for easily looking up when resolveReference flag is specified
|
||||
this.inputFiles.set(file.fileName, file.content);
|
||||
if (ts.getBaseFileName(file.fileName).toLowerCase() === "tsconfig.json") {
|
||||
const configJson = ts.parseConfigFileTextToJson(file.fileName, file.content);
|
||||
if (configJson.config === undefined) {
|
||||
throw new Error(`Failed to parse test tsconfig.json: ${configJson.error.messageText}`);
|
||||
}
|
||||
|
||||
// Extend our existing compiler options so that we can also support tsconfig only options
|
||||
if (configJson.config.compilerOptions) {
|
||||
const baseDirectory = ts.normalizePath(ts.getDirectoryPath(file.fileName));
|
||||
const tsConfig = ts.convertCompilerOptionsFromJson(configJson.config.compilerOptions, baseDirectory, file.fileName);
|
||||
|
||||
if (!tsConfig.errors || !tsConfig.errors.length) {
|
||||
compilationOptions = ts.extend(compilationOptions, tsConfig.options);
|
||||
}
|
||||
}
|
||||
configFileName = file.fileName;
|
||||
}
|
||||
|
||||
@@ -372,8 +390,8 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
// Entry points from fourslash.ts
|
||||
public goToMarker(name = "") {
|
||||
const marker = this.getMarkerByName(name);
|
||||
public goToMarker(name: string | Marker = "") {
|
||||
const marker = typeof name === "string" ? this.getMarkerByName(name) : name;
|
||||
if (this.activeFile.fileName !== marker.fileName) {
|
||||
this.openFile(marker.fileName);
|
||||
}
|
||||
@@ -382,10 +400,37 @@ namespace FourSlash {
|
||||
if (marker.position === -1 || marker.position > content.length) {
|
||||
throw new Error(`Marker "${name}" has been invalidated by unrecoverable edits to the file.`);
|
||||
}
|
||||
this.lastKnownMarker = name;
|
||||
const mName = typeof name === "string" ? name : this.markerName(marker);
|
||||
this.lastKnownMarker = mName;
|
||||
this.goToPosition(marker.position);
|
||||
}
|
||||
|
||||
public goToEachMarker(action: () => void) {
|
||||
const markers = this.getMarkers();
|
||||
assert(markers.length);
|
||||
for (const marker of markers) {
|
||||
this.goToMarker(marker);
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
public goToEachRange(action: () => void) {
|
||||
const ranges = this.getRanges();
|
||||
assert(ranges.length);
|
||||
for (const range of ranges) {
|
||||
this.goToRangeStart(range);
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
private markerName(m: Marker): string {
|
||||
return ts.forEachEntry(this.testData.markerPositions, (marker, name) => {
|
||||
if (marker === m) {
|
||||
return name;
|
||||
}
|
||||
})!;
|
||||
}
|
||||
|
||||
public goToPosition(pos: number) {
|
||||
this.currentCaretPosition = pos;
|
||||
}
|
||||
@@ -425,7 +470,8 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
private messageAtLastKnownMarker(message: string) {
|
||||
return "Marker: " + this.lastKnownMarker + "\n" + message;
|
||||
const locationDescription = this.lastKnownMarker ? this.lastKnownMarker : this.getLineColStringAtPosition(this.currentCaretPosition);
|
||||
return `At ${locationDescription}: ${message}`;
|
||||
}
|
||||
|
||||
private assertionMessageAtLastKnownMarker(msg: string) {
|
||||
@@ -503,10 +549,21 @@ namespace FourSlash {
|
||||
Harness.IO.log("Unexpected error(s) found. Error list is:");
|
||||
}
|
||||
|
||||
errors.forEach(function (error: ts.Diagnostic) {
|
||||
Harness.IO.log(" minChar: " + error.start +
|
||||
", limChar: " + (error.start + error.length) +
|
||||
", message: " + ts.flattenDiagnosticMessageText(error.messageText, Harness.IO.newLine()) + "\n");
|
||||
for (const { start, length, messageText } of errors) {
|
||||
Harness.IO.log(" minChar: " + start +
|
||||
", limChar: " + (start + length) +
|
||||
", message: " + ts.flattenDiagnosticMessageText(messageText, Harness.IO.newLine()) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
public verifyNoErrors() {
|
||||
ts.forEachKey(this.inputFiles, fileName => {
|
||||
const errors = this.getDiagnostics(fileName);
|
||||
if (errors.length) {
|
||||
this.printErrorLog(/*expectErrors*/ false, errors);
|
||||
const error = errors[0];
|
||||
this.raiseError(`Found an error: ${error.file.fileName}@${error.start}: ${error.messageText}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -535,7 +592,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
public verifyGoToDefinitionIs(endMarker: string | string[]) {
|
||||
this.verifyGoToXWorker(endMarker instanceof Array ? endMarker : [endMarker], () => this.getGoToDefinition());
|
||||
this.verifyGoToXWorker(toArray(endMarker), () => this.getGoToDefinition());
|
||||
}
|
||||
|
||||
public verifyGoToDefinition(arg0: any, endMarkerNames?: string | string[]) {
|
||||
@@ -543,7 +600,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
private getGoToDefinition(): ts.DefinitionInfo[] {
|
||||
return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition)
|
||||
return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
}
|
||||
|
||||
public verifyGoToType(arg0: any, endMarkerNames?: string | string[]) {
|
||||
@@ -555,7 +612,7 @@ namespace FourSlash {
|
||||
if (endMarkerNames) {
|
||||
this.verifyGoToXPlain(arg0, endMarkerNames, getDefs);
|
||||
}
|
||||
else if (arg0 instanceof Array) {
|
||||
else if (ts.isArray(arg0)) {
|
||||
const pairs: [string | string[], string | string[]][] = arg0;
|
||||
for (const [start, end] of pairs) {
|
||||
this.verifyGoToXPlain(start, end, getDefs);
|
||||
@@ -572,13 +629,8 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
private verifyGoToXPlain(startMarkerNames: string | string[], endMarkerNames: string | string[], getDefs: () => ts.DefinitionInfo[] | undefined) {
|
||||
if (startMarkerNames instanceof Array) {
|
||||
for (const start of startMarkerNames) {
|
||||
this.verifyGoToXSingle(start, endMarkerNames, getDefs);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.verifyGoToXSingle(startMarkerNames, endMarkerNames, getDefs);
|
||||
for (const start of toArray(startMarkerNames)) {
|
||||
this.verifyGoToXSingle(start, endMarkerNames, getDefs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,7 +642,7 @@ namespace FourSlash {
|
||||
|
||||
private verifyGoToXSingle(startMarkerName: string, endMarkerNames: string | string[], getDefs: () => ts.DefinitionInfo[] | undefined) {
|
||||
this.goToMarker(startMarkerName);
|
||||
this.verifyGoToXWorker(endMarkerNames instanceof Array ? endMarkerNames : [endMarkerNames], getDefs);
|
||||
this.verifyGoToXWorker(toArray(endMarkerNames), getDefs);
|
||||
}
|
||||
|
||||
private verifyGoToXWorker(endMarkers: string[], getDefs: () => ts.DefinitionInfo[] | undefined) {
|
||||
@@ -817,7 +869,7 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public verifyCompletionEntryDetails(entryName: string, expectedText: string, expectedDocumentation?: string, kind?: string) {
|
||||
public verifyCompletionEntryDetails(entryName: string, expectedText: string, expectedDocumentation?: string, kind?: string, tags?: ts.JSDocTagInfo[]) {
|
||||
const details = this.getCompletionEntryDetails(entryName);
|
||||
|
||||
assert(details, "no completion entry available");
|
||||
@@ -831,9 +883,78 @@ namespace FourSlash {
|
||||
if (kind !== undefined) {
|
||||
assert.equal(details.kind, kind, this.assertionMessageAtLastKnownMarker("completion entry kind"));
|
||||
}
|
||||
|
||||
if (tags !== undefined) {
|
||||
assert.equal(details.tags.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags"));
|
||||
ts.zipWith(tags, details.tags, (expectedTag, actualTag) => {
|
||||
assert.equal(expectedTag.name, actualTag.name);
|
||||
assert.equal(expectedTag.text, actualTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public verifyReferencesAre(expectedReferences: Range[]) {
|
||||
/** Use `getProgram` instead of accessing this directly. */
|
||||
private _program: ts.Program;
|
||||
/** Use `getChecker` instead of accessing this directly. */
|
||||
private _checker: ts.TypeChecker;
|
||||
|
||||
private getProgram(): ts.Program {
|
||||
return this._program || (this._program = this.languageService.getProgram());
|
||||
}
|
||||
|
||||
private getChecker() {
|
||||
return this._checker || (this._checker = this.getProgram().getTypeChecker());
|
||||
}
|
||||
|
||||
private getSourceFile(): ts.SourceFile {
|
||||
const { fileName } = this.activeFile;
|
||||
const result = this.getProgram().getSourceFile(fileName);
|
||||
if (!result) {
|
||||
throw new Error(`Could not get source file ${fileName}`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private getNode(): ts.Node {
|
||||
return ts.getTouchingPropertyName(this.getSourceFile(), this.currentCaretPosition);
|
||||
}
|
||||
|
||||
private goToAndGetNode(range: Range): ts.Node {
|
||||
this.goToRangeStart(range);
|
||||
const node = this.getNode();
|
||||
this.verifyRange("touching property name", range, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
private verifyRange(desc: string, expected: Range, actual: ts.Node) {
|
||||
const actualStart = actual.getStart();
|
||||
const actualEnd = actual.getEnd();
|
||||
if (actualStart !== expected.start || actualEnd !== expected.end) {
|
||||
this.raiseError(`${desc} should be ${expected.start}-${expected.end}, got ${actualStart}-${actualEnd}`);
|
||||
}
|
||||
}
|
||||
|
||||
private verifySymbol(symbol: ts.Symbol, declarationRanges: Range[]) {
|
||||
const { declarations } = symbol;
|
||||
if (declarations.length !== declarationRanges.length) {
|
||||
this.raiseError(`Expected to get ${declarationRanges.length} declarations, got ${declarations.length}`);
|
||||
}
|
||||
|
||||
ts.zipWith(declarations, declarationRanges, (decl, range) => {
|
||||
this.verifyRange("symbol declaration", range, decl);
|
||||
});
|
||||
}
|
||||
|
||||
public verifySymbolAtLocation(startRange: Range, declarationRanges: Range[]): void {
|
||||
const node = this.goToAndGetNode(startRange);
|
||||
const symbol = this.getChecker().getSymbolAtLocation(node);
|
||||
if (!symbol) {
|
||||
this.raiseError("Could not get symbol at location");
|
||||
}
|
||||
this.verifySymbol(symbol, declarationRanges);
|
||||
}
|
||||
|
||||
private verifyReferencesAre(expectedReferences: Range[]) {
|
||||
const actualReferences = this.getReferencesAtCaret() || [];
|
||||
|
||||
if (actualReferences.length > expectedReferences.length) {
|
||||
@@ -859,9 +980,8 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public verifyReferencesOf({fileName, start}: Range, references: Range[]) {
|
||||
this.openFile(fileName);
|
||||
this.goToPosition(start);
|
||||
public verifyReferencesOf(range: Range, references: Range[]) {
|
||||
this.goToRangeStart(range);
|
||||
this.verifyReferencesAre(references);
|
||||
}
|
||||
|
||||
@@ -873,8 +993,77 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public verifyRangesWithSameTextReferenceEachOther() {
|
||||
this.rangesByText().forEach(ranges => this.verifyRangesReferenceEachOther(ranges));
|
||||
public verifyReferenceGroups(startRanges: Range | Range[], parts: Array<{ definition: string, ranges: Range[] }>): void {
|
||||
interface ReferenceJson { definition: string; ranges: ts.ReferenceEntry[]; }
|
||||
type ReferencesJson = ReferenceJson[];
|
||||
const fullExpected = parts.map<ReferenceJson>(({ definition, ranges }) => ({ definition, ranges: ranges.map(rangeToReferenceEntry) }));
|
||||
|
||||
for (const startRange of toArray(startRanges)) {
|
||||
this.goToRangeStart(startRange);
|
||||
const fullActual = ts.map<ts.ReferencedSymbol, ReferenceJson>(this.findReferencesAtCaret(), ({ definition, references }) => ({
|
||||
definition: definition.displayParts.map(d => d.text).join(""),
|
||||
ranges: references
|
||||
}));
|
||||
this.assertObjectsEqual<ReferencesJson>(fullActual, fullExpected);
|
||||
}
|
||||
|
||||
function rangeToReferenceEntry(r: Range): ts.ReferenceEntry {
|
||||
const { isWriteAccess, isDefinition, isInString } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false, isInString: undefined };
|
||||
const result: ts.ReferenceEntry = { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess: !!isWriteAccess, isDefinition: !!isDefinition };
|
||||
if (isInString !== undefined) {
|
||||
result.isInString = isInString;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public verifyNoReferences(markerNameOrRange?: string | Range) {
|
||||
if (markerNameOrRange) {
|
||||
if (typeof markerNameOrRange === "string") {
|
||||
this.goToMarker(markerNameOrRange);
|
||||
}
|
||||
else {
|
||||
this.goToRangeStart(markerNameOrRange);
|
||||
}
|
||||
}
|
||||
|
||||
const refs = this.getReferencesAtCaret();
|
||||
if (refs && refs.length) {
|
||||
console.log(refs);
|
||||
this.raiseError("Expected getReferences to fail");
|
||||
}
|
||||
}
|
||||
|
||||
public verifySingleReferenceGroup(definition: string, ranges?: Range[]) {
|
||||
ranges = ranges || this.getRanges();
|
||||
this.verifyReferenceGroups(ranges, [{ definition, ranges }]);
|
||||
}
|
||||
|
||||
private assertObjectsEqual<T>(fullActual: T, fullExpected: T, msgPrefix = ""): void {
|
||||
const recur = <U>(actual: U, expected: U, path: string) => {
|
||||
const fail = (msg: string) => {
|
||||
console.log("Expected:", stringify(fullExpected));
|
||||
console.log("Actual: ", stringify(fullActual));
|
||||
this.raiseError(`${msgPrefix}At ${path}: ${msg}`);
|
||||
};
|
||||
|
||||
for (const key in actual) if (ts.hasProperty(actual as any, key)) {
|
||||
const ak = actual[key], ek = expected[key];
|
||||
if (typeof ak === "object" && typeof ek === "object") {
|
||||
recur(ak, ek, path ? path + "." + key : key);
|
||||
}
|
||||
else if (ak !== ek) {
|
||||
fail(`Expected '${key}' to be '${ek}', got '${ak}'`);
|
||||
}
|
||||
}
|
||||
for (const key in expected) if (ts.hasProperty(expected as any, key)) {
|
||||
if (!ts.hasProperty(actual as any, key)) {
|
||||
fail(`${msgPrefix}Missing property '${key}'`);
|
||||
}
|
||||
}
|
||||
};
|
||||
recur(fullActual, fullExpected, "");
|
||||
|
||||
}
|
||||
|
||||
public verifyDisplayPartsOfReferencedSymbol(expected: ts.SymbolDisplayPart[]) {
|
||||
@@ -948,7 +1137,7 @@ namespace FourSlash {
|
||||
public verifyQuickInfos(namesAndTexts: { [name: string]: string | [string, string] }) {
|
||||
for (const name in namesAndTexts) if (ts.hasProperty(namesAndTexts, name)) {
|
||||
const text = namesAndTexts[name];
|
||||
if (text instanceof Array) {
|
||||
if (ts.isArray(text)) {
|
||||
assert(text.length === 2);
|
||||
const [expectedText, expectedDocumentation] = text;
|
||||
this.verifyQuickInfoAt(name, expectedText, expectedDocumentation);
|
||||
@@ -974,7 +1163,9 @@ namespace FourSlash {
|
||||
|
||||
public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; },
|
||||
displayParts: ts.SymbolDisplayPart[],
|
||||
documentation: ts.SymbolDisplayPart[]) {
|
||||
documentation: ts.SymbolDisplayPart[],
|
||||
tags: ts.JSDocTagInfo[]
|
||||
) {
|
||||
|
||||
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind"));
|
||||
@@ -982,11 +1173,39 @@ namespace FourSlash {
|
||||
assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan"));
|
||||
assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.displayParts), TestState.getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts"));
|
||||
assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.documentation), TestState.getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation"));
|
||||
assert.equal(actualQuickInfo.tags.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags"));
|
||||
ts.zipWith(tags, actualQuickInfo.tags, (expectedTag, actualTag) => {
|
||||
assert.equal(expectedTag.name, actualTag.name);
|
||||
assert.equal(expectedTag.text, actualTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name));
|
||||
});
|
||||
}
|
||||
|
||||
public verifyRenameLocations(findInStrings: boolean, findInComments: boolean, ranges?: Range[]) {
|
||||
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
|
||||
if (renameInfo.canRename) {
|
||||
public verifyRangesAreRenameLocations(options?: Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges?: Range[] }) {
|
||||
const ranges = ts.isArray(options) ? options : options && options.ranges || this.getRanges();
|
||||
this.verifyRenameLocations(ranges, { ranges, ...options });
|
||||
}
|
||||
|
||||
public verifyRenameLocations(startRanges: Range | Range[], options: Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges: Range[] }) {
|
||||
let findInStrings: boolean, findInComments: boolean, ranges: Range[];
|
||||
if (ts.isArray(options)) {
|
||||
findInStrings = findInComments = false;
|
||||
ranges = options;
|
||||
}
|
||||
else {
|
||||
findInStrings = !!options.findInStrings;
|
||||
findInComments = !!options.findInComments;
|
||||
ranges = options.ranges;
|
||||
}
|
||||
|
||||
for (const startRange of toArray(startRanges)) {
|
||||
this.goToRangeStart(startRange);
|
||||
|
||||
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
|
||||
if (!renameInfo.canRename) {
|
||||
this.raiseError("Expected rename to succeed, but it actually failed.");
|
||||
break;
|
||||
}
|
||||
|
||||
let references = this.languageService.findRenameLocations(
|
||||
this.activeFile.fileName, this.currentCaretPosition, findInStrings, findInComments);
|
||||
|
||||
@@ -1008,13 +1227,10 @@ namespace FourSlash {
|
||||
|
||||
ts.zipWith(references, ranges, (reference, range) => {
|
||||
if (reference.textSpan.start !== range.start || ts.textSpanEnd(reference.textSpan) !== range.end) {
|
||||
this.raiseError("Rename location results do not match.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + JSON.stringify(references));
|
||||
this.raiseError("Rename location results do not match.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + stringify(references));
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.raiseError("Expected rename to succeed, but it actually failed.");
|
||||
}
|
||||
}
|
||||
|
||||
public verifyQuickInfoExists(negative: boolean) {
|
||||
@@ -1075,6 +1291,16 @@ namespace FourSlash {
|
||||
assert.equal(ts.displayPartsToString(actualDocComment), docComment, this.assertionMessageAtLastKnownMarker("current signature help doc comment"));
|
||||
}
|
||||
|
||||
public verifyCurrentSignatureHelpTags(tags: ts.JSDocTagInfo[]) {
|
||||
const actualTags = this.getActiveSignatureHelpItem().tags;
|
||||
|
||||
assert.equal(actualTags.length, tags.length, this.assertionMessageAtLastKnownMarker("signature help tags"));
|
||||
ts.zipWith(tags, actualTags, (expectedTag, actualTag) => {
|
||||
assert.equal(expectedTag.name, actualTag.name);
|
||||
assert.equal(expectedTag.text, actualTag.text, this.assertionMessageAtLastKnownMarker("signature help tag " + actualTag.name));
|
||||
});
|
||||
}
|
||||
|
||||
public verifySignatureHelpCount(expected: number) {
|
||||
const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
|
||||
const actual = help && help.items ? help.items.length : 0;
|
||||
@@ -1385,13 +1611,6 @@ namespace FourSlash {
|
||||
Harness.IO.log(membersString);
|
||||
}
|
||||
|
||||
public printReferences() {
|
||||
const references = this.getReferencesAtCaret();
|
||||
ts.forEach(references, entry => {
|
||||
Harness.IO.log(stringify(entry));
|
||||
});
|
||||
}
|
||||
|
||||
public printContext() {
|
||||
ts.forEach(this.languageServiceAdapterHost.getFilenames(), Harness.IO.log);
|
||||
}
|
||||
@@ -1567,7 +1786,7 @@ namespace FourSlash {
|
||||
if (ch === "\r") {
|
||||
this.currentCaretPosition--;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private applyEdits(fileName: string, edits: ts.TextChange[], isFormattingEdit = false): number {
|
||||
@@ -1669,6 +1888,11 @@ namespace FourSlash {
|
||||
this.goToPosition(len);
|
||||
}
|
||||
|
||||
public goToRangeStart({fileName, start}: Range) {
|
||||
this.openFile(fileName);
|
||||
this.goToPosition(start);
|
||||
}
|
||||
|
||||
public goToTypeDefinition(definitionIndex: number) {
|
||||
const definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
if (!definitions || !definitions.length) {
|
||||
@@ -1751,17 +1975,41 @@ namespace FourSlash {
|
||||
|
||||
const unsatisfiedRanges: Range[] = [];
|
||||
|
||||
const delayedErrors: string[] = [];
|
||||
for (const range of ranges) {
|
||||
const length = range.end - range.start;
|
||||
const matchingImpl = ts.find(implementations, impl =>
|
||||
range.fileName === impl.fileName && range.start === impl.textSpan.start && length === impl.textSpan.length);
|
||||
if (matchingImpl) {
|
||||
if (range.marker && range.marker.data) {
|
||||
const expected = <{ displayParts?: ts.SymbolDisplayPart[], parts: string[], kind?: string }>range.marker.data;
|
||||
if (expected.displayParts) {
|
||||
if (!ts.arrayIsEqualTo(expected.displayParts, matchingImpl.displayParts, displayPartIsEqualTo)) {
|
||||
delayedErrors.push(`Mismatched display parts: expected ${JSON.stringify(expected.displayParts)}, actual ${JSON.stringify(matchingImpl.displayParts)}`);
|
||||
}
|
||||
}
|
||||
else if (expected.parts) {
|
||||
const actualParts = matchingImpl.displayParts.map(p => p.text);
|
||||
if (!ts.arrayIsEqualTo(expected.parts, actualParts)) {
|
||||
delayedErrors.push(`Mismatched non-tagged display parts: expected ${JSON.stringify(expected.parts)}, actual ${JSON.stringify(actualParts)}`);
|
||||
}
|
||||
}
|
||||
if (expected.kind !== undefined) {
|
||||
if (expected.kind !== matchingImpl.kind) {
|
||||
delayedErrors.push(`Mismatched kind: expected ${JSON.stringify(expected.kind)}, actual ${JSON.stringify(matchingImpl.kind)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matchingImpl.matched = true;
|
||||
}
|
||||
else {
|
||||
unsatisfiedRanges.push(range);
|
||||
}
|
||||
}
|
||||
if (delayedErrors.length) {
|
||||
this.raiseError(delayedErrors.join("\n"));
|
||||
}
|
||||
|
||||
const unmatchedImplementations = implementations.filter(impl => !impl.matched);
|
||||
if (unmatchedImplementations.length || unsatisfiedRanges.length) {
|
||||
@@ -1786,6 +2034,10 @@ namespace FourSlash {
|
||||
function implementationsAreEqual(a: ImplementationLocationInformation, b: ImplementationLocationInformation) {
|
||||
return a.fileName === b.fileName && TestState.textSpansEqual(a.textSpan, b.textSpan);
|
||||
}
|
||||
|
||||
function displayPartIsEqualTo(a: ts.SymbolDisplayPart, b: ts.SymbolDisplayPart): boolean {
|
||||
return a.kind === b.kind && a.text === b.text;
|
||||
}
|
||||
}
|
||||
|
||||
public getMarkers(): Marker[] {
|
||||
@@ -1858,8 +2110,7 @@ namespace FourSlash {
|
||||
|
||||
public verifyCurrentFileContent(text: string) {
|
||||
const actual = this.getFileContent(this.activeFile.fileName);
|
||||
const replaceNewlines = (str: string) => str.replace(/\r\n/g, "\n");
|
||||
if (replaceNewlines(actual) !== replaceNewlines(text)) {
|
||||
if (normalizeNewLines(actual) !== normalizeNewLines(text)) {
|
||||
throw new Error("verifyCurrentFileContent\n" +
|
||||
"\tExpected: \"" + text + "\"\n" +
|
||||
"\t Actual: \"" + actual + "\"");
|
||||
@@ -2022,7 +2273,7 @@ namespace FourSlash {
|
||||
* Because codefixes are only applied on the working file, it is unsafe
|
||||
* to apply this more than once (consider a refactoring across files).
|
||||
*/
|
||||
public verifyRangeAfterCodeFix(expectedText: string, errorCode?: number) {
|
||||
public verifyRangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number) {
|
||||
const ranges = this.getRanges();
|
||||
if (ranges.length !== 1) {
|
||||
this.raiseError("Exactly one range should be specified in the testfile.");
|
||||
@@ -2030,11 +2281,15 @@ namespace FourSlash {
|
||||
|
||||
const fileName = this.activeFile.fileName;
|
||||
|
||||
this.applyCodeFixActions(fileName, this.getCodeFixActions(fileName, errorCode));
|
||||
this.applyCodeAction(fileName, this.getCodeFixActions(fileName, errorCode), index);
|
||||
|
||||
const actualText = this.rangeText(ranges[0]);
|
||||
|
||||
if (this.removeWhitespace(actualText) !== this.removeWhitespace(expectedText)) {
|
||||
const result = includeWhiteSpace
|
||||
? normalizeNewLines(actualText) === normalizeNewLines(expectedText)
|
||||
: this.removeWhitespace(actualText) === this.removeWhitespace(expectedText);
|
||||
|
||||
if (!result) {
|
||||
this.raiseError(`Actual text doesn't match expected text. Actual:\n'${actualText}'\nExpected:\n'${expectedText}'`);
|
||||
}
|
||||
}
|
||||
@@ -2042,7 +2297,7 @@ namespace FourSlash {
|
||||
/**
|
||||
* Applies fixes for the errors in fileName and compares the results to
|
||||
* expectedContents after all fixes have been applied.
|
||||
|
||||
*
|
||||
* Note: applying one codefix may generate another (eg: remove duplicate implements
|
||||
* may generate an extends -> interface conversion fix).
|
||||
* @param expectedContents The contents of the file after the fixes are applied.
|
||||
@@ -2051,7 +2306,7 @@ namespace FourSlash {
|
||||
public verifyFileAfterCodeFix(expectedContents: string, fileName?: string) {
|
||||
fileName = fileName ? fileName : this.activeFile.fileName;
|
||||
|
||||
this.applyCodeFixActions(fileName, this.getCodeFixActions(fileName));
|
||||
this.applyCodeAction(fileName, this.getCodeFixActions(fileName));
|
||||
|
||||
const actualContents: string = this.getFileContent(fileName);
|
||||
if (this.removeWhitespace(actualContents) !== this.removeWhitespace(expectedContents)) {
|
||||
@@ -2064,16 +2319,24 @@ namespace FourSlash {
|
||||
* @param fileName Path to file where error should be retrieved from.
|
||||
*/
|
||||
private getCodeFixActions(fileName: string, errorCode?: number): ts.CodeAction[] {
|
||||
const diagnostics: ts.Diagnostic[] = this.getDiagnostics(fileName);
|
||||
const diagnosticsForCodeFix = this.getDiagnostics(fileName).map(diagnostic => {
|
||||
return {
|
||||
start: diagnostic.start,
|
||||
length: diagnostic.length,
|
||||
code: diagnostic.code
|
||||
};
|
||||
});
|
||||
const dedupedDiagnositcs = ts.deduplicate(diagnosticsForCodeFix, ts.equalOwnProperties);
|
||||
|
||||
let actions: ts.CodeAction[] = undefined;
|
||||
for (const diagnostic of diagnostics) {
|
||||
|
||||
for (const diagnostic of dedupedDiagnositcs) {
|
||||
|
||||
if (errorCode && errorCode !== diagnostic.code) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]);
|
||||
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code], this.formatCodeSettings);
|
||||
if (newActions && newActions.length) {
|
||||
actions = actions ? actions.concat(newActions) : newActions;
|
||||
}
|
||||
@@ -2081,12 +2344,20 @@ namespace FourSlash {
|
||||
return actions;
|
||||
}
|
||||
|
||||
private applyCodeFixActions(fileName: string, actions: ts.CodeAction[]): void {
|
||||
if (!(actions && actions.length === 1)) {
|
||||
this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found.`);
|
||||
private applyCodeAction(fileName: string, actions: ts.CodeAction[], index?: number): void {
|
||||
if (index === undefined) {
|
||||
if (!(actions && actions.length === 1)) {
|
||||
this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found.`);
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
else {
|
||||
if (!(actions && actions.length >= index + 1)) {
|
||||
this.raiseError(`Should find at least ${index + 1} codefix(es), but ${actions ? actions.length : "none"} found.`);
|
||||
}
|
||||
}
|
||||
|
||||
const fileChanges = ts.find(actions[0].changes, change => change.fileName === fileName);
|
||||
const fileChanges = ts.find(actions[index].changes, change => change.fileName === fileName);
|
||||
if (!fileChanges) {
|
||||
this.raiseError("The CodeFix found doesn't provide any changes in this file.");
|
||||
}
|
||||
@@ -2128,22 +2399,22 @@ namespace FourSlash {
|
||||
|
||||
if (expected === undefined) {
|
||||
if (actual) {
|
||||
this.raiseError(name + " failed - expected no template but got {newText: \"" + actual.newText + "\" caretOffset: " + actual.caretOffset + "}");
|
||||
this.raiseError(`${name} failed - expected no template but got {newText: "${actual.newText}", caretOffset: ${actual.caretOffset}}`);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (actual === undefined) {
|
||||
this.raiseError(name + " failed - expected the template {newText: \"" + actual.newText + "\" caretOffset: " + actual.caretOffset + "} but got nothing instead");
|
||||
this.raiseError(`${name} failed - expected the template {newText: "${expected.newText}", caretOffset: "${expected.caretOffset}"} but got nothing instead`);
|
||||
}
|
||||
|
||||
if (actual.newText !== expected.newText) {
|
||||
this.raiseError(name + " failed - expected insertion:\n" + this.clarifyNewlines(expected.newText) + "\nactual insertion:\n" + this.clarifyNewlines(actual.newText));
|
||||
this.raiseError(`${name} failed - expected insertion:\n"${this.clarifyNewlines(expected.newText)}"\nactual insertion:\n"${this.clarifyNewlines(actual.newText)}"`);
|
||||
}
|
||||
|
||||
if (actual.caretOffset !== expected.caretOffset) {
|
||||
this.raiseError(name + " failed - expected caretOffset: " + expected.caretOffset + ",\nactual caretOffset:" + actual.caretOffset);
|
||||
this.raiseError(`${name} failed - expected caretOffset: ${expected.caretOffset}\nactual caretOffset:${actual.caretOffset}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2361,40 +2632,60 @@ namespace FourSlash {
|
||||
return this.languageService.getDocumentHighlights(this.activeFile.fileName, this.currentCaretPosition, filesToSearch);
|
||||
}
|
||||
|
||||
public verifyDocumentHighlightsAtPositionListContains(fileName: string, start: number, end: number, fileNamesToSearch: string[], kind?: string) {
|
||||
const documentHighlights = this.getDocumentHighlightsAtCurrentPosition(fileNamesToSearch);
|
||||
|
||||
if (!documentHighlights || documentHighlights.length === 0) {
|
||||
this.raiseError("verifyDocumentHighlightsAtPositionListContains failed - found 0 highlights, expected at least one.");
|
||||
public verifyRangesAreOccurrences(isWriteAccess?: boolean) {
|
||||
const ranges = this.getRanges();
|
||||
for (const r of ranges) {
|
||||
this.goToRangeStart(r);
|
||||
this.verifyOccurrencesAtPositionListCount(ranges.length);
|
||||
for (const range of ranges) {
|
||||
this.verifyOccurrencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const documentHighlight of documentHighlights) {
|
||||
if (documentHighlight.fileName === fileName) {
|
||||
const { highlightSpans } = documentHighlight;
|
||||
public verifyRangesWithSameTextAreRenameLocations() {
|
||||
this.rangesByText().forEach(ranges => this.verifyRangesAreRenameLocations(ranges));
|
||||
}
|
||||
|
||||
for (const highlight of highlightSpans) {
|
||||
if (highlight && highlight.textSpan.start === start && ts.textSpanEnd(highlight.textSpan) === end) {
|
||||
if (typeof kind !== "undefined" && highlight.kind !== kind) {
|
||||
this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - item "kind" value does not match, actual: ${highlight.kind}, expected: ${kind}.`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
public verifyRangesWithSameTextAreDocumentHighlights() {
|
||||
this.rangesByText().forEach(ranges => this.verifyRangesAreDocumentHighlights(ranges));
|
||||
}
|
||||
|
||||
public verifyRangesAreDocumentHighlights(ranges?: Range[]) {
|
||||
ranges = ranges || this.getRanges();
|
||||
const fileNames = unique(ranges, range => range.fileName);
|
||||
for (const range of ranges) {
|
||||
this.goToRangeStart(range);
|
||||
this.verifyDocumentHighlights(ranges, fileNames);
|
||||
}
|
||||
}
|
||||
|
||||
private verifyDocumentHighlights(expectedRanges: Range[], fileNames: string[] = [this.activeFile.fileName]) {
|
||||
const documentHighlights = this.getDocumentHighlightsAtCurrentPosition(fileNames) || [];
|
||||
|
||||
for (const dh of documentHighlights) {
|
||||
if (fileNames.indexOf(dh.fileName) === -1) {
|
||||
this.raiseError(`verifyDocumentHighlights failed - got highlights in unexpected file name ${dh.fileName}`);
|
||||
}
|
||||
}
|
||||
|
||||
const missingItem = { fileName: fileName, start: start, end: end, kind: kind };
|
||||
this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(documentHighlights)})`);
|
||||
}
|
||||
for (const fileName of fileNames) {
|
||||
const expectedRangesInFile = expectedRanges.filter(r => r.fileName === fileName);
|
||||
const highlights = ts.find(documentHighlights, dh => dh.fileName === fileName);
|
||||
if (!highlights) {
|
||||
this.raiseError(`verifyDocumentHighlights failed - found no highlights in ${fileName}`);
|
||||
}
|
||||
const spansInFile = highlights.highlightSpans.sort((s1, s2) => s1.textSpan.start - s2.textSpan.start);
|
||||
|
||||
public verifyDocumentHighlightsAtPositionListCount(expectedCount: number, fileNamesToSearch: string[]) {
|
||||
const documentHighlights = this.getDocumentHighlightsAtCurrentPosition(fileNamesToSearch);
|
||||
const actualCount = documentHighlights
|
||||
? documentHighlights.reduce((currentCount, { highlightSpans }) => currentCount + highlightSpans.length, 0)
|
||||
: 0;
|
||||
if (expectedRangesInFile.length !== spansInFile.length) {
|
||||
this.raiseError(`verifyDocumentHighlights failed - In ${fileName}, expected ${expectedRangesInFile.length} highlights, got ${spansInFile.length}`);
|
||||
}
|
||||
|
||||
if (expectedCount !== actualCount) {
|
||||
this.raiseError("verifyDocumentHighlightsAtPositionListCount failed - actual: " + actualCount + ", expected:" + expectedCount);
|
||||
ts.zipWith(expectedRangesInFile, spansInFile, (expectedRange, span) => {
|
||||
if (span.textSpan.start !== expectedRange.start || ts.textSpanEnd(span.textSpan) !== expectedRange.end) {
|
||||
this.raiseError(`verifyDocumentHighlights failed - span does not match, actual: ${stringify(span.textSpan)}, expected: ${expectedRange.start}--${expectedRange.end}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2410,6 +2701,11 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public printAvailableCodeFixes() {
|
||||
const codeFixes = this.getCodeFixActions(this.activeFile.fileName);
|
||||
Harness.IO.log(stringify(codeFixes));
|
||||
}
|
||||
|
||||
// Get the text of the entire line the caret is currently at
|
||||
private getCurrentLineContent() {
|
||||
const text = this.getFileContent(this.activeFile.fileName);
|
||||
@@ -2987,7 +3283,7 @@ ${code}
|
||||
}
|
||||
|
||||
// Add the remaining text
|
||||
flush(undefined);
|
||||
flush(/*lastSafeCharIndex*/ undefined);
|
||||
|
||||
if (openRanges.length > 0) {
|
||||
const openRange = openRanges[0];
|
||||
@@ -3021,6 +3317,20 @@ ${code}
|
||||
function stringify(data: any, replacer?: (key: string, value: any) => any): string {
|
||||
return JSON.stringify(data, replacer, 2);
|
||||
}
|
||||
|
||||
/** Collects an array of unique outputs. */
|
||||
function unique<T>(inputs: T[], getOutput: (t: T) => string): string[] {
|
||||
const set = ts.createMap<true>();
|
||||
for (const input of inputs) {
|
||||
const out = getOutput(input);
|
||||
set.set(out, true);
|
||||
}
|
||||
return ts.arrayFrom(set.keys());
|
||||
}
|
||||
|
||||
function toArray<T>(x: T | T[]): T[] {
|
||||
return ts.isArray(x) ? x : [x];
|
||||
}
|
||||
}
|
||||
|
||||
namespace FourSlashInterface {
|
||||
@@ -3059,10 +3369,22 @@ namespace FourSlashInterface {
|
||||
// Moves the caret to the specified marker,
|
||||
// or the anonymous marker ('/**/') if no name
|
||||
// is given
|
||||
public marker(name?: string) {
|
||||
public marker(name?: string | FourSlash.Marker) {
|
||||
this.state.goToMarker(name);
|
||||
}
|
||||
|
||||
public eachMarker(action: () => void) {
|
||||
this.state.goToEachMarker(action);
|
||||
}
|
||||
|
||||
public rangeStart(range: FourSlash.Range) {
|
||||
this.state.goToRangeStart(range);
|
||||
}
|
||||
|
||||
public eachRange(action: () => void) {
|
||||
this.state.goToEachRange(action);
|
||||
}
|
||||
|
||||
public bof() {
|
||||
this.state.goToBOF();
|
||||
}
|
||||
@@ -3265,14 +3587,26 @@ namespace FourSlashInterface {
|
||||
this.state.verifyGetEmitOutputContentsForCurrentFile(expected);
|
||||
}
|
||||
|
||||
public referencesAre(ranges: FourSlash.Range[]) {
|
||||
this.state.verifyReferencesAre(ranges);
|
||||
public symbolAtLocation(startRange: FourSlash.Range, ...declarationRanges: FourSlash.Range[]) {
|
||||
this.state.verifySymbolAtLocation(startRange, declarationRanges);
|
||||
}
|
||||
|
||||
public referencesOf(start: FourSlash.Range, references: FourSlash.Range[]) {
|
||||
this.state.verifyReferencesOf(start, references);
|
||||
}
|
||||
|
||||
public referenceGroups(startRanges: FourSlash.Range[], parts: Array<{ definition: string, ranges: FourSlash.Range[] }>) {
|
||||
this.state.verifyReferenceGroups(startRanges, parts);
|
||||
}
|
||||
|
||||
public noReferences(markerNameOrRange?: string | FourSlash.Range) {
|
||||
this.state.verifyNoReferences(markerNameOrRange);
|
||||
}
|
||||
|
||||
public singleReferenceGroup(definition: string, ranges?: FourSlash.Range[]) {
|
||||
this.state.verifySingleReferenceGroup(definition, ranges);
|
||||
}
|
||||
|
||||
public rangesReferenceEachOther(ranges?: FourSlash.Range[]) {
|
||||
this.state.verifyRangesReferenceEachOther(ranges);
|
||||
}
|
||||
@@ -3281,10 +3615,6 @@ namespace FourSlashInterface {
|
||||
this.state.verifyDisplayPartsOfReferencedSymbol(expected);
|
||||
}
|
||||
|
||||
public rangesWithSameTextReferenceEachOther() {
|
||||
this.state.verifyRangesWithSameTextReferenceEachOther();
|
||||
}
|
||||
|
||||
public currentParameterHelpArgumentNameIs(name: string) {
|
||||
this.state.verifyCurrentParameterHelpName(name);
|
||||
}
|
||||
@@ -3301,6 +3631,10 @@ namespace FourSlashInterface {
|
||||
this.state.verifyCurrentSignatureHelpDocComment(docComment);
|
||||
}
|
||||
|
||||
public currentSignatureHelpTagsAre(tags: ts.JSDocTagInfo[]) {
|
||||
this.state.verifyCurrentSignatureHelpTags(tags);
|
||||
}
|
||||
|
||||
public signatureHelpCountIs(expected: number) {
|
||||
this.state.verifySignatureHelpCount(expected);
|
||||
}
|
||||
@@ -3321,6 +3655,10 @@ namespace FourSlashInterface {
|
||||
this.state.verifyCurrentSignatureHelpIs(expected);
|
||||
}
|
||||
|
||||
public noErrors() {
|
||||
this.state.verifyNoErrors();
|
||||
}
|
||||
|
||||
public numberOfErrorsInCurrentFile(expected: number) {
|
||||
this.state.verifyNumberOfErrorsInCurrentFile(expected);
|
||||
}
|
||||
@@ -3369,8 +3707,8 @@ namespace FourSlashInterface {
|
||||
this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true);
|
||||
}
|
||||
|
||||
public rangeAfterCodeFix(expectedText: string, errorCode?: number): void {
|
||||
this.state.verifyRangeAfterCodeFix(expectedText, errorCode);
|
||||
public rangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number): void {
|
||||
this.state.verifyRangeAfterCodeFix(expectedText, includeWhiteSpace, errorCode, index);
|
||||
}
|
||||
|
||||
public importFixAtPosition(expectedTextArray: string[], errorCode?: number): void {
|
||||
@@ -3413,16 +3751,28 @@ namespace FourSlashInterface {
|
||||
this.state.verifyOccurrencesAtPositionListCount(expectedCount);
|
||||
}
|
||||
|
||||
public documentHighlightsAtPositionContains(range: FourSlash.Range, fileNamesToSearch: string[], kind?: string) {
|
||||
this.state.verifyDocumentHighlightsAtPositionListContains(range.fileName, range.start, range.end, fileNamesToSearch, kind);
|
||||
public rangesAreOccurrences(isWriteAccess?: boolean) {
|
||||
this.state.verifyRangesAreOccurrences(isWriteAccess);
|
||||
}
|
||||
|
||||
public documentHighlightsAtPositionCount(expectedCount: number, fileNamesToSearch: string[]) {
|
||||
this.state.verifyDocumentHighlightsAtPositionListCount(expectedCount, fileNamesToSearch);
|
||||
public rangesWithSameTextAreRenameLocations() {
|
||||
this.state.verifyRangesWithSameTextAreRenameLocations();
|
||||
}
|
||||
|
||||
public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string) {
|
||||
this.state.verifyCompletionEntryDetails(entryName, text, documentation, kind);
|
||||
public rangesAreRenameLocations(options?: FourSlash.Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges?: FourSlash.Range[] }) {
|
||||
this.state.verifyRangesAreRenameLocations(options);
|
||||
}
|
||||
|
||||
public rangesAreDocumentHighlights(ranges?: FourSlash.Range[]) {
|
||||
this.state.verifyRangesAreDocumentHighlights(ranges);
|
||||
}
|
||||
|
||||
public rangesWithSameTextAreDocumentHighlights() {
|
||||
this.state.verifyRangesWithSameTextAreDocumentHighlights();
|
||||
}
|
||||
|
||||
public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string, tags?: ts.JSDocTagInfo[]) {
|
||||
this.state.verifyCompletionEntryDetails(entryName, text, documentation, kind, tags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3447,13 +3797,13 @@ namespace FourSlashInterface {
|
||||
this.state.verifyRenameInfoFailed(message);
|
||||
}
|
||||
|
||||
public renameLocations(findInStrings: boolean, findInComments: boolean, ranges?: FourSlash.Range[]) {
|
||||
this.state.verifyRenameLocations(findInStrings, findInComments, ranges);
|
||||
public renameLocations(startRanges: FourSlash.Range | FourSlash.Range[], options: FourSlash.Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges: FourSlash.Range[] }) {
|
||||
this.state.verifyRenameLocations(startRanges, options);
|
||||
}
|
||||
|
||||
public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; },
|
||||
displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) {
|
||||
this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation);
|
||||
displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: ts.JSDocTagInfo[]) {
|
||||
this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation, tags);
|
||||
}
|
||||
|
||||
public getSyntacticDiagnostics(expected: string) {
|
||||
@@ -3537,11 +3887,11 @@ namespace FourSlashInterface {
|
||||
}
|
||||
|
||||
public printCurrentFileStateWithWhitespace() {
|
||||
this.state.printCurrentFileState(/*makeWhitespaceVisible*/true);
|
||||
this.state.printCurrentFileState(/*makeWhitespaceVisible*/ true);
|
||||
}
|
||||
|
||||
public printCurrentFileStateWithoutCaret() {
|
||||
this.state.printCurrentFileState(/*makeWhitespaceVisible*/false, /*makeCaretVisible*/false);
|
||||
this.state.printCurrentFileState(/*makeWhitespaceVisible*/ false, /*makeCaretVisible*/ false);
|
||||
}
|
||||
|
||||
public printCurrentQuickInfo() {
|
||||
@@ -3556,6 +3906,10 @@ namespace FourSlashInterface {
|
||||
this.state.printCompletionListMembers();
|
||||
}
|
||||
|
||||
public printAvailableCodeFixes() {
|
||||
this.state.printAvailableCodeFixes();
|
||||
}
|
||||
|
||||
public printBreakpointLocation(pos: number) {
|
||||
this.state.printBreakpointLocation(pos);
|
||||
}
|
||||
@@ -3579,10 +3933,6 @@ namespace FourSlashInterface {
|
||||
this.state.printNavigationBar();
|
||||
}
|
||||
|
||||
public printReferences() {
|
||||
this.state.printReferences();
|
||||
}
|
||||
|
||||
public printContext() {
|
||||
this.state.printContext();
|
||||
}
|
||||
|
||||
+52
-98
@@ -34,11 +34,18 @@ var _chai: typeof chai = require("chai");
|
||||
var assert: typeof _chai.assert = _chai.assert;
|
||||
declare var __dirname: string; // Node-specific
|
||||
var global: NodeJS.Global = <any>Function("return this").call(undefined);
|
||||
declare namespace NodeJS {
|
||||
export interface Global {
|
||||
WScript: typeof WScript;
|
||||
ActiveXObject: typeof ActiveXObject;
|
||||
}
|
||||
|
||||
declare var window: {};
|
||||
declare var XMLHttpRequest: {
|
||||
new(): XMLHttpRequest;
|
||||
};
|
||||
interface XMLHttpRequest {
|
||||
readonly readyState: number;
|
||||
readonly responseText: string;
|
||||
readonly status: number;
|
||||
open(method: string, url: string, async?: boolean, user?: string, password?: string): void;
|
||||
send(data?: string): void;
|
||||
setRequestHeader(header: string, value: string): void;
|
||||
}
|
||||
/* tslint:enable:no-var-keyword */
|
||||
|
||||
@@ -47,14 +54,10 @@ namespace Utils {
|
||||
export const enum ExecutionEnvironment {
|
||||
Node,
|
||||
Browser,
|
||||
CScript
|
||||
}
|
||||
|
||||
export function getExecutionEnvironment() {
|
||||
if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
|
||||
return ExecutionEnvironment.CScript;
|
||||
}
|
||||
else if (typeof window !== "undefined") {
|
||||
if (typeof window !== "undefined") {
|
||||
return ExecutionEnvironment.Browser;
|
||||
}
|
||||
else {
|
||||
@@ -80,7 +83,6 @@ namespace Utils {
|
||||
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
|
||||
const environment = getExecutionEnvironment();
|
||||
switch (environment) {
|
||||
case ExecutionEnvironment.CScript:
|
||||
case ExecutionEnvironment.Browser:
|
||||
eval(fileContents);
|
||||
break;
|
||||
@@ -189,7 +191,7 @@ namespace Utils {
|
||||
for (const childName in node) {
|
||||
if (childName === "parent" || childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator" ||
|
||||
// for now ignore jsdoc comments
|
||||
childName === "jsDocComment") {
|
||||
childName === "jsDocComment" || childName === "checkJsDirective") {
|
||||
continue;
|
||||
}
|
||||
const child = (<any>node)[childName];
|
||||
@@ -503,83 +505,6 @@ namespace Harness {
|
||||
export const virtualFileSystemRoot = "/";
|
||||
|
||||
namespace IOImpl {
|
||||
declare class Enumerator {
|
||||
public atEnd(): boolean;
|
||||
public moveNext(): boolean;
|
||||
public item(): any;
|
||||
constructor(o: any);
|
||||
}
|
||||
|
||||
export namespace CScript {
|
||||
let fso: any;
|
||||
if (global.ActiveXObject) {
|
||||
fso = new global.ActiveXObject("Scripting.FileSystemObject");
|
||||
}
|
||||
else {
|
||||
fso = {};
|
||||
}
|
||||
|
||||
export const args = () => ts.sys.args;
|
||||
export const getExecutingFilePath = () => ts.sys.getExecutingFilePath();
|
||||
export const exit = (exitCode: number) => ts.sys.exit(exitCode);
|
||||
export const resolvePath = (path: string) => ts.sys.resolvePath(path);
|
||||
export const getCurrentDirectory = () => ts.sys.getCurrentDirectory();
|
||||
export const newLine = () => harnessNewLine;
|
||||
export const useCaseSensitiveFileNames = () => ts.sys.useCaseSensitiveFileNames;
|
||||
|
||||
export const readFile: typeof IO.readFile = path => ts.sys.readFile(path);
|
||||
export const writeFile: typeof IO.writeFile = (path, content) => ts.sys.writeFile(path, content);
|
||||
export const directoryName: typeof IO.directoryName = fso.GetParentFolderName;
|
||||
export const getDirectories: typeof IO.getDirectories = dir => ts.sys.getDirectories(dir);
|
||||
export const directoryExists: typeof IO.directoryExists = fso.FolderExists;
|
||||
export const fileExists: typeof IO.fileExists = fso.FileExists;
|
||||
export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine;
|
||||
export const getEnvironmentVariable: typeof IO.getEnvironmentVariable = name => ts.sys.getEnvironmentVariable(name);
|
||||
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude, include) => ts.sys.readDirectory(path, extension, exclude, include);
|
||||
|
||||
export function createDirectory(path: string) {
|
||||
if (directoryExists(path)) {
|
||||
fso.CreateFolder(path);
|
||||
}
|
||||
}
|
||||
|
||||
export function deleteFile(path: string) {
|
||||
if (fileExists(path)) {
|
||||
fso.DeleteFile(path, true); // true: delete read-only files
|
||||
}
|
||||
}
|
||||
|
||||
export let listFiles: typeof IO.listFiles = (path, spec?, options?) => {
|
||||
options = options || <{ recursive?: boolean; }>{};
|
||||
function filesInFolder(folder: any, root: string): string[] {
|
||||
let paths: string[] = [];
|
||||
let fc: any;
|
||||
|
||||
if (options.recursive) {
|
||||
fc = new Enumerator(folder.subfolders);
|
||||
|
||||
for (; !fc.atEnd(); fc.moveNext()) {
|
||||
paths = paths.concat(filesInFolder(fc.item(), root + "\\" + fc.item().Name));
|
||||
}
|
||||
}
|
||||
|
||||
fc = new Enumerator(folder.files);
|
||||
|
||||
for (; !fc.atEnd(); fc.moveNext()) {
|
||||
if (!spec || fc.item().Name.match(spec)) {
|
||||
paths.push(root + "\\" + fc.item().Name);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
const folder: any = fso.GetFolder(path);
|
||||
|
||||
return filesInFolder(folder, path);
|
||||
};
|
||||
}
|
||||
|
||||
export namespace Node {
|
||||
declare const require: any;
|
||||
let fs: any, pathModule: any;
|
||||
@@ -827,16 +752,16 @@ namespace Harness {
|
||||
}
|
||||
}
|
||||
|
||||
switch (Utils.getExecutionEnvironment()) {
|
||||
case Utils.ExecutionEnvironment.CScript:
|
||||
IO = IOImpl.CScript;
|
||||
break;
|
||||
const environment = Utils.getExecutionEnvironment();
|
||||
switch (environment) {
|
||||
case Utils.ExecutionEnvironment.Node:
|
||||
IO = IOImpl.Node;
|
||||
break;
|
||||
case Utils.ExecutionEnvironment.Browser:
|
||||
IO = IOImpl.Network;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown value '${environment}' for ExecutionEnvironment.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -860,7 +785,7 @@ namespace Harness {
|
||||
/** Aggregate various writes into a single array of lines. Useful for passing to the
|
||||
* TypeScript compiler to fill with source code or errors.
|
||||
*/
|
||||
export class WriterAggregator implements ITextWriter {
|
||||
export class WriterAggregator {
|
||||
public lines: string[] = [];
|
||||
public currentLine = <string>undefined;
|
||||
|
||||
@@ -909,10 +834,15 @@ namespace Harness {
|
||||
export const defaultLibFileName = "lib.d.ts";
|
||||
export const es2015DefaultLibFileName = "lib.es2015.d.ts";
|
||||
|
||||
// Cache of lib files from "built/local"
|
||||
const libFileNameSourceFileMap = ts.createMapFromTemplate<ts.SourceFile>({
|
||||
[defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest)
|
||||
});
|
||||
|
||||
// Cache of lib files from "tests/lib/"
|
||||
const testLibFileNameSourceFileMap = ts.createMap<ts.SourceFile>();
|
||||
const es6TestLibFileNameSourceFileMap = ts.createMap<ts.SourceFile>();
|
||||
|
||||
export function getDefaultLibrarySourceFile(fileName = defaultLibFileName): ts.SourceFile {
|
||||
if (!isDefaultLibraryFile(fileName)) {
|
||||
return undefined;
|
||||
@@ -954,7 +884,8 @@ namespace Harness {
|
||||
useCaseSensitiveFileNames: boolean,
|
||||
// the currentDirectory is needed for rwcRunner to passed in specified current directory to compiler host
|
||||
currentDirectory: string,
|
||||
newLineKind?: ts.NewLineKind): ts.CompilerHost {
|
||||
newLineKind?: ts.NewLineKind,
|
||||
libFiles?: string): ts.CompilerHost {
|
||||
|
||||
// Local get canonical file name function, that depends on passed in parameter for useCaseSensitiveFileNames
|
||||
const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
@@ -986,6 +917,24 @@ namespace Harness {
|
||||
}
|
||||
}
|
||||
|
||||
if (libFiles) {
|
||||
// Because @libFiles don't change between execution. We would cache the result of the files and reuse it to speed help compilation
|
||||
for (const fileName of libFiles.split(",")) {
|
||||
const libFileName = "tests/lib/" + fileName;
|
||||
|
||||
if (scriptTarget <= ts.ScriptTarget.ES5) {
|
||||
if (!testLibFileNameSourceFileMap.get(libFileName)) {
|
||||
testLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName), scriptTarget));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!es6TestLibFileNameSourceFileMap.get(libFileName)) {
|
||||
es6TestLibFileNameSourceFileMap.set(libFileName, createSourceFileAndAssertInvariants(libFileName, IO.readFile(libFileName), scriptTarget));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceFile(fileName: string) {
|
||||
fileName = ts.normalizePath(fileName);
|
||||
const fromFileMap = fileMap.get(toPath(fileName));
|
||||
@@ -997,6 +946,9 @@ namespace Harness {
|
||||
fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, Harness.IO.readFile(tsFn), scriptTarget);
|
||||
return fourslashSourceFile;
|
||||
}
|
||||
else if (ts.startsWith(fileName, "tests/lib/")) {
|
||||
return scriptTarget <= ts.ScriptTarget.ES5 ? testLibFileNameSourceFileMap.get(fileName) : es6TestLibFileNameSourceFileMap.get(fileName);
|
||||
}
|
||||
else {
|
||||
// Don't throw here -- the compiler might be looking for a test that actually doesn't exist as part of the TC
|
||||
// Return if it is other library file, otherwise return undefined
|
||||
@@ -1208,7 +1160,8 @@ namespace Harness {
|
||||
if (options.libFiles) {
|
||||
for (const fileName of options.libFiles.split(",")) {
|
||||
const libFileName = "tests/lib/" + fileName;
|
||||
programFiles.push({ unitName: libFileName, content: normalizeLineEndings(IO.readFile(libFileName), Harness.IO.newLine()) });
|
||||
// Content is undefined here because in createCompilerHost we will create sourceFile for the lib file and cache the result
|
||||
programFiles.push({ unitName: libFileName, content: undefined });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1221,7 +1174,8 @@ namespace Harness {
|
||||
options.target,
|
||||
useCaseSensitiveFileNames,
|
||||
currentDirectory,
|
||||
options.newLine);
|
||||
options.newLine,
|
||||
options.libFiles);
|
||||
|
||||
let traceResults: string[];
|
||||
if (options.traceResolution) {
|
||||
@@ -1843,7 +1797,7 @@ namespace Harness {
|
||||
if (currentFileContent === undefined) {
|
||||
currentFileContent = "";
|
||||
}
|
||||
else {
|
||||
else if (currentFileContent !== "") {
|
||||
// End-of-line
|
||||
currentFileContent = currentFileContent + "\n";
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace Harness.LanguageService {
|
||||
export class ScriptInfo {
|
||||
public version: number = 1;
|
||||
public version = 1;
|
||||
public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = [];
|
||||
private lineMap: number[] = undefined;
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Harness.LanguageService {
|
||||
protected virtualFileSystem: Utils.VirtualFileSystem = new Utils.VirtualFileSystem(virtualFileSystemRoot, /*useCaseSensitiveFilenames*/false);
|
||||
|
||||
constructor(protected cancellationToken = DefaultHostCancellationToken.Instance,
|
||||
protected settings = ts.getDefaultCompilerOptions()) {
|
||||
protected settings = ts.getDefaultCompilerOptions()) {
|
||||
}
|
||||
|
||||
public getNewLine(): string {
|
||||
@@ -135,7 +135,7 @@ namespace Harness.LanguageService {
|
||||
|
||||
public getFilenames(): string[] {
|
||||
const fileNames: string[] = [];
|
||||
for (const virtualEntry of this.virtualFileSystem.getAllFileEntries()){
|
||||
for (const virtualEntry of this.virtualFileSystem.getAllFileEntries()) {
|
||||
const scriptInfo = virtualEntry.content;
|
||||
if (scriptInfo.isRootFile) {
|
||||
// only include root files here
|
||||
@@ -169,9 +169,9 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param line 0 based index
|
||||
* @param col 0 based index
|
||||
*/
|
||||
* @param line 0 based index
|
||||
* @param col 0 based index
|
||||
*/
|
||||
public positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter {
|
||||
const script: ScriptInfo = this.getScriptInfo(fileName);
|
||||
assert.isOk(script);
|
||||
@@ -210,9 +210,9 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[] {
|
||||
return ts.matchFiles(path, extensions, exclude, include,
|
||||
/*useCaseSensitiveFileNames*/false,
|
||||
this.getCurrentDirectory(),
|
||||
(p) => this.virtualFileSystem.getAccessibleFileSystemEntries(p));
|
||||
/*useCaseSensitiveFileNames*/ false,
|
||||
this.getCurrentDirectory(),
|
||||
(p) => this.virtualFileSystem.getAccessibleFileSystemEntries(p));
|
||||
}
|
||||
readFile(path: string): string {
|
||||
const snapshot = this.getScriptSnapshot(path);
|
||||
@@ -594,7 +594,7 @@ namespace Harness.LanguageService {
|
||||
class SessionServerHost implements ts.server.ServerHost, ts.server.Logger {
|
||||
args: string[] = [];
|
||||
newLine: string;
|
||||
useCaseSensitiveFileNames: boolean = false;
|
||||
useCaseSensitiveFileNames = false;
|
||||
|
||||
constructor(private host: NativeLanguageServiceHost) {
|
||||
this.newLine = this.host.getNewLine();
|
||||
@@ -724,6 +724,87 @@ namespace Harness.LanguageService {
|
||||
createHash(s: string) {
|
||||
return s;
|
||||
}
|
||||
|
||||
require(_initialDir: string, _moduleName: string): ts.server.RequireResult {
|
||||
switch (_moduleName) {
|
||||
// Adds to the Quick Info a fixed string and a string from the config file
|
||||
// and replaces the first display part
|
||||
case "quickinfo-augmeneter":
|
||||
return {
|
||||
module: () => ({
|
||||
create(info: ts.server.PluginCreateInfo) {
|
||||
const proxy = makeDefaultProxy(info);
|
||||
const langSvc: any = info.languageService;
|
||||
proxy.getQuickInfoAtPosition = function () {
|
||||
const parts = langSvc.getQuickInfoAtPosition.apply(langSvc, arguments);
|
||||
if (parts.displayParts.length > 0) {
|
||||
parts.displayParts[0].text = "Proxied";
|
||||
}
|
||||
parts.displayParts.push({ text: info.config.message, kind: "punctuation" });
|
||||
return parts;
|
||||
};
|
||||
|
||||
return proxy;
|
||||
}
|
||||
}),
|
||||
error: undefined
|
||||
};
|
||||
|
||||
// Throws during initialization
|
||||
case "create-thrower":
|
||||
return {
|
||||
module: () => ({
|
||||
create() {
|
||||
throw new Error("I am not a well-behaved plugin");
|
||||
}
|
||||
}),
|
||||
error: undefined
|
||||
};
|
||||
|
||||
// Adds another diagnostic
|
||||
case "diagnostic-adder":
|
||||
return {
|
||||
module: () => ({
|
||||
create(info: ts.server.PluginCreateInfo) {
|
||||
const proxy = makeDefaultProxy(info);
|
||||
proxy.getSemanticDiagnostics = function (filename: string) {
|
||||
const prev = info.languageService.getSemanticDiagnostics(filename);
|
||||
const sourceFile: ts.SourceFile = info.languageService.getSourceFile(filename);
|
||||
prev.push({
|
||||
category: ts.DiagnosticCategory.Warning,
|
||||
file: sourceFile,
|
||||
code: 9999,
|
||||
length: 3,
|
||||
messageText: `Plugin diagnostic`,
|
||||
start: 0
|
||||
});
|
||||
return prev;
|
||||
};
|
||||
return proxy;
|
||||
}
|
||||
}),
|
||||
error: undefined
|
||||
};
|
||||
|
||||
default:
|
||||
return {
|
||||
module: undefined,
|
||||
error: "Could not resolve module"
|
||||
};
|
||||
}
|
||||
|
||||
function makeDefaultProxy(info: ts.server.PluginCreateInfo) {
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
const proxy = Object.create(/*prototype*/ null);
|
||||
const langSvc: any = info.languageService;
|
||||
for (const k of Object.keys(langSvc)) {
|
||||
proxy[k] = function () {
|
||||
return langSvc[k].apply(langSvc, arguments);
|
||||
};
|
||||
}
|
||||
return proxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ServerLanguageServiceAdapter implements LanguageServiceAdapter {
|
||||
@@ -737,13 +818,17 @@ namespace Harness.LanguageService {
|
||||
// This host is just a proxy for the clientHost, it uses the client
|
||||
// host to answer server queries about files on disk
|
||||
const serverHost = new SessionServerHost(clientHost);
|
||||
const server = new ts.server.Session(serverHost,
|
||||
{ isCancellationRequested: () => false },
|
||||
/*useOneInferredProject*/ false,
|
||||
/*typingsInstaller*/ undefined,
|
||||
Utils.byteLength,
|
||||
process.hrtime, serverHost,
|
||||
/*canUseEvents*/ true);
|
||||
const opts: ts.server.SessionOptions = {
|
||||
host: serverHost,
|
||||
cancellationToken: ts.server.nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
typingsInstaller: undefined,
|
||||
byteLength: Utils.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger: serverHost,
|
||||
canUseEvents: true
|
||||
};
|
||||
const server = new ts.server.Session(opts);
|
||||
|
||||
// Fake the connection between the client and the server
|
||||
serverHost.writeMessage = client.onMessage.bind(client);
|
||||
|
||||
@@ -422,7 +422,7 @@ namespace Harness.SourceMapRecorder {
|
||||
const jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.code);
|
||||
if (prevEmittedCol < jsFileText.length) {
|
||||
// There is remaining text on this line that will be part of next source span so write marker that continues
|
||||
writeSourceMapMarker(undefined, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true);
|
||||
writeSourceMapMarker(/*currentSpan*/ undefined, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true);
|
||||
}
|
||||
|
||||
// Emit Source text
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
{
|
||||
"extends": "../tsconfig-base",
|
||||
"compilerOptions": {
|
||||
"removeComments": false,
|
||||
@@ -6,6 +6,10 @@
|
||||
"declaration": false,
|
||||
"types": [
|
||||
"node", "mocha", "chai"
|
||||
],
|
||||
"lib": [
|
||||
"es6",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
@@ -77,8 +81,9 @@
|
||||
"../services/codefixes/helpers.ts",
|
||||
"../services/codefixes/importFixes.ts",
|
||||
"../services/codefixes/unusedIdentifierFixes.ts",
|
||||
"../services/harness.ts",
|
||||
"../services/codefixes/disableJsDiagnostics.ts",
|
||||
|
||||
"harness.ts",
|
||||
"sourceMapRecorder.ts",
|
||||
"harnessLanguageService.ts",
|
||||
"fourslash.ts",
|
||||
@@ -91,7 +96,7 @@
|
||||
"rwcRunner.ts",
|
||||
"test262Runner.ts",
|
||||
"runner.ts",
|
||||
"../server/protocol.d.ts",
|
||||
"../server/protocol.ts",
|
||||
"../server/session.ts",
|
||||
"../server/client.ts",
|
||||
"../server/editorServices.ts",
|
||||
@@ -118,6 +123,10 @@
|
||||
"./unittests/initializeTSConfig.ts",
|
||||
"./unittests/compileOnSave.ts",
|
||||
"./unittests/typingsInstaller.ts",
|
||||
"./unittests/projectErrors.ts"
|
||||
"./unittests/projectErrors.ts",
|
||||
"./unittests/printer.ts",
|
||||
"./unittests/transform.ts",
|
||||
"./unittests/customTransforms.ts",
|
||||
"./unittests/textChanges.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
namespace ts {
|
||||
interface File {
|
||||
@@ -64,8 +64,16 @@ namespace ts {
|
||||
getLogFileName: (): string => undefined
|
||||
};
|
||||
|
||||
const projectService = new server.ProjectService(serverHost, logger, { isCancellationRequested: () => false }, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined);
|
||||
const rootScriptInfo = projectService.getOrCreateScriptInfo(rootFile, /* openedByClient */true, /*containingProject*/ undefined);
|
||||
const svcOpts: server.ProjectServiceOptions = {
|
||||
host: serverHost,
|
||||
logger,
|
||||
cancellationToken: { isCancellationRequested: () => false },
|
||||
useSingleInferredProject: false,
|
||||
typingsInstaller: undefined
|
||||
};
|
||||
const projectService = new server.ProjectService(svcOpts);
|
||||
const rootScriptInfo = projectService.getOrCreateScriptInfo(rootFile, /* openedByClient */ true, /*containingProject*/ undefined);
|
||||
|
||||
const project = projectService.createInferredProjectWithRootFileIfNecessary(rootScriptInfo);
|
||||
project.setCompilerOptions({ module: ts.ModuleKind.AMD } );
|
||||
return {
|
||||
@@ -203,4 +211,4 @@ namespace ts {
|
||||
assert.isTrue(diags.length === 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace ts {
|
||||
assertParseResult(["--lib", "es5,invalidOption", "0.ts"],
|
||||
{
|
||||
errors: [{
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace ts {
|
||||
start: undefined,
|
||||
length: undefined,
|
||||
}, {
|
||||
messageText: "Argument for '--jsx' option must be: 'preserve', 'react'",
|
||||
messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace ts {
|
||||
start: undefined,
|
||||
length: undefined,
|
||||
}, {
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace ts {
|
||||
start: undefined,
|
||||
length: undefined,
|
||||
}, {
|
||||
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'",
|
||||
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace ts {
|
||||
start: undefined,
|
||||
length: undefined,
|
||||
}, {
|
||||
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'esnext'",
|
||||
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'esnext'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
@@ -191,7 +191,7 @@ namespace ts {
|
||||
start: undefined,
|
||||
length: undefined,
|
||||
}, {
|
||||
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'",
|
||||
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
@@ -263,7 +263,7 @@ namespace ts {
|
||||
assertParseResult(["--lib", "es5,", "es7", "0.ts"],
|
||||
{
|
||||
errors: [{
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
@@ -283,7 +283,7 @@ namespace ts {
|
||||
assertParseResult(["--lib", "es5, ", "es7", "0.ts"],
|
||||
{
|
||||
errors: [{
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace ts.projectSystem {
|
||||
import CommandNames = server.CommandNames;
|
||||
const nullCancellationToken = server.nullCancellationToken;
|
||||
|
||||
function createTestTypingsInstaller(host: server.ServerHost) {
|
||||
return new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
|
||||
@@ -30,6 +31,20 @@ namespace ts.projectSystem {
|
||||
}
|
||||
}
|
||||
|
||||
function createSession(host: server.ServerHost, typingsInstaller?: server.ITypingsInstaller): server.Session {
|
||||
const opts: server.SessionOptions = {
|
||||
host,
|
||||
cancellationToken: nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
typingsInstaller: typingsInstaller || server.nullTypingsInstaller,
|
||||
byteLength: Utils.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger: nullLogger,
|
||||
canUseEvents: false
|
||||
};
|
||||
return new server.Session(opts);
|
||||
}
|
||||
|
||||
describe("for configured projects", () => {
|
||||
let moduleFile1: FileOrFolder;
|
||||
let file1Consumer1: FileOrFolder;
|
||||
@@ -112,7 +127,7 @@ namespace ts.projectSystem {
|
||||
it("should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", () => {
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||
|
||||
@@ -137,7 +152,7 @@ namespace ts.projectSystem {
|
||||
it("should be up-to-date with the reference map changes", () => {
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||
|
||||
@@ -184,7 +199,7 @@ namespace ts.projectSystem {
|
||||
it("should be up-to-date with changes made in non-open files", () => {
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([moduleFile1], session);
|
||||
|
||||
@@ -202,7 +217,7 @@ namespace ts.projectSystem {
|
||||
it("should be up-to-date with deleted files", () => {
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([moduleFile1], session);
|
||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]);
|
||||
@@ -217,7 +232,7 @@ namespace ts.projectSystem {
|
||||
it("should be up-to-date with newly created files", () => {
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([moduleFile1], session);
|
||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]);
|
||||
@@ -254,7 +269,7 @@ namespace ts.projectSystem {
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1] }]);
|
||||
@@ -271,7 +286,7 @@ namespace ts.projectSystem {
|
||||
it("should return all files if a global file changed shape", () => {
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([globalFile3], session);
|
||||
const changeGlobalFile3ShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
|
||||
@@ -297,7 +312,7 @@ namespace ts.projectSystem {
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
openFilesForSession([moduleFile1], session);
|
||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, []);
|
||||
});
|
||||
@@ -315,7 +330,7 @@ namespace ts.projectSystem {
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
openFilesForSession([moduleFile1], session);
|
||||
|
||||
const file1ChangeShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
|
||||
@@ -344,7 +359,7 @@ namespace ts.projectSystem {
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
openFilesForSession([moduleFile1], session);
|
||||
|
||||
const file1ChangeShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
|
||||
@@ -366,7 +381,7 @@ namespace ts.projectSystem {
|
||||
};
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer1Consumer1, globalFile3, configFile, libFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer1Consumer1] }]);
|
||||
@@ -399,7 +414,7 @@ namespace ts.projectSystem {
|
||||
};
|
||||
const host = createServerHost([file1, file2, configFile]);
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([file1, file2], session);
|
||||
const file1AffectedListRequest = makeSessionRequest<server.protocol.FileRequestArgs>(CommandNames.CompileOnSaveAffectedFileList, { file: file1.path });
|
||||
@@ -495,7 +510,7 @@ namespace ts.projectSystem {
|
||||
const emitOutput = host.readFile(path + ".js");
|
||||
assert.equal(emitOutput, f.content + newLine, "content of emit output should be identical with the input + newline");
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it("should emit specified file", () => {
|
||||
const file1 = {
|
||||
@@ -512,7 +527,7 @@ namespace ts.projectSystem {
|
||||
};
|
||||
const host = createServerHost([file1, file2, configFile, libFile], { newLine: "\r\n" });
|
||||
const typingsInstaller = createTestTypingsInstaller(host);
|
||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
||||
const session = createSession(host, typingsInstaller);
|
||||
|
||||
openFilesForSession([file1, file2], session);
|
||||
const compileFileRequest = makeSessionRequest<server.protocol.CompileOnSaveEmitFileRequestArgs>(CommandNames.CompileOnSaveEmitFile, { file: file1.path, projectFileName: configFile.path });
|
||||
@@ -520,7 +535,7 @@ namespace ts.projectSystem {
|
||||
|
||||
const expectedEmittedFileName = "/a/b/f1.js";
|
||||
assert.isTrue(host.fileExists(expectedEmittedFileName));
|
||||
assert.equal(host.readFile(expectedEmittedFileName), `"use strict";\r\nfunction Foo() { return 10; }\r\nexports.Foo = Foo;\r\n`);
|
||||
assert.equal(host.readFile(expectedEmittedFileName), `"use strict";\r\nexports.__esModule = true;\r\nfunction Foo() { return 10; }\r\nexports.Foo = Foo;\r\n`);
|
||||
});
|
||||
|
||||
it("shoud not emit js files in external projects", () => {
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--jsx' option must be: 'preserve', 'react'",
|
||||
messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -122,7 +122,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -150,7 +150,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'",
|
||||
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -176,7 +176,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'esnext'",
|
||||
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'esnext'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -202,7 +202,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'",
|
||||
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -233,7 +233,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -264,7 +264,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -295,7 +295,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
@@ -326,7 +326,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
|
||||
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace ts {
|
||||
});
|
||||
|
||||
it("Converts simple code snippet correctly", () => {
|
||||
runTest(`/// <reference path="file.ts" />
|
||||
runTest(`/// <reference path="file.ts" />
|
||||
var x: string = "string";
|
||||
console.log(x);`);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/// <reference path="..\..\compiler\emitter.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe("customTransforms", () => {
|
||||
function emitsCorrectly(name: string, sources: { file: string, text: string }[], customTransformers: CustomTransformers) {
|
||||
it(name, () => {
|
||||
const roots = sources.map(source => createSourceFile(source.file, source.text, ScriptTarget.ES2015));
|
||||
const fileMap = arrayToMap(roots, file => file.fileName);
|
||||
const outputs = createMap<string>();
|
||||
const options: CompilerOptions = {};
|
||||
const host: CompilerHost = {
|
||||
getSourceFile: (fileName) => fileMap.get(fileName),
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
getCurrentDirectory: () => "",
|
||||
getDirectories: () => [],
|
||||
getCanonicalFileName: (fileName) => fileName,
|
||||
useCaseSensitiveFileNames: () => true,
|
||||
getNewLine: () => "\n",
|
||||
fileExists: (fileName) => fileMap.has(fileName),
|
||||
readFile: (fileName) => fileMap.has(fileName) ? fileMap.get(fileName).text : undefined,
|
||||
writeFile: (fileName, text) => outputs.set(fileName, text),
|
||||
};
|
||||
|
||||
const program = createProgram(arrayFrom(fileMap.keys()), options, host);
|
||||
program.emit(/*targetSourceFile*/ undefined, host.writeFile, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ false, customTransformers);
|
||||
Harness.Baseline.runBaseline(`customTransforms/${name}.js`, () => {
|
||||
let content = "";
|
||||
for (const [file, text] of arrayFrom(outputs.entries())) {
|
||||
if (content) content += "\n\n";
|
||||
content += `// [${file}]\n`;
|
||||
content += text;
|
||||
}
|
||||
return content;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const sources = [{
|
||||
file: "source.ts",
|
||||
text: `
|
||||
function f1() { }
|
||||
class c() { }
|
||||
enum e { }
|
||||
// leading
|
||||
function f2() { } // trailing
|
||||
`
|
||||
}];
|
||||
|
||||
const before: TransformerFactory<SourceFile> = context => {
|
||||
return file => visitEachChild(file, visit, context);
|
||||
function visit(node: Node): VisitResult<Node> {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return visitFunction(<FunctionDeclaration>node);
|
||||
default:
|
||||
return visitEachChild(node, visit, context);
|
||||
}
|
||||
}
|
||||
function visitFunction(node: FunctionDeclaration) {
|
||||
addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, "@before", /*hasTrailingNewLine*/ true);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
const after: TransformerFactory<SourceFile> = context => {
|
||||
return file => visitEachChild(file, visit, context);
|
||||
function visit(node: Node): VisitResult<Node> {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VariableStatement:
|
||||
return visitVariableStatement(<VariableStatement>node);
|
||||
default:
|
||||
return visitEachChild(node, visit, context);
|
||||
}
|
||||
}
|
||||
function visitVariableStatement(node: VariableStatement) {
|
||||
addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, "@after");
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
emitsCorrectly("before", sources, { before: [before] });
|
||||
emitsCorrectly("after", sources, { after: [after] });
|
||||
emitsCorrectly("both", sources, { before: [before], after: [after] });
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\..\compiler\commandLineParser.ts" />
|
||||
|
||||
namespace ts {
|
||||
@@ -6,21 +6,11 @@ namespace ts {
|
||||
function initTSConfigCorrectly(name: string, commandLinesArgs: string[]) {
|
||||
describe(name, () => {
|
||||
const commandLine = parseCommandLine(commandLinesArgs);
|
||||
const initResult = generateTSConfig(commandLine.options, commandLine.fileNames);
|
||||
const initResult = generateTSConfig(commandLine.options, commandLine.fileNames, "\n");
|
||||
const outputFileName = `tsConfig/${name.replace(/[^a-z0-9\-. ]/ig, "")}/tsconfig.json`;
|
||||
|
||||
it(`Correct output for ${outputFileName}`, () => {
|
||||
Harness.Baseline.runBaseline(outputFileName, () => {
|
||||
if (initResult) {
|
||||
return JSON.stringify(initResult, undefined, 4);
|
||||
}
|
||||
else {
|
||||
// This can happen if compiler recieve invalid compiler-options
|
||||
/* tslint:disable:no-null-keyword */
|
||||
return null;
|
||||
/* tslint:enable:no-null-keyword */
|
||||
}
|
||||
});
|
||||
Harness.Baseline.runBaseline(outputFileName, () => initResult);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -288,5 +288,24 @@ namespace ts {
|
||||
*/`);
|
||||
});
|
||||
});
|
||||
describe("getFirstToken", () => {
|
||||
it("gets jsdoc", () => {
|
||||
const root = ts.createSourceFile("foo.ts", "/** comment */var a = true;", ts.ScriptTarget.ES5, /*setParentNodes*/ true);
|
||||
assert.isDefined(root);
|
||||
assert.equal(root.kind, ts.SyntaxKind.SourceFile);
|
||||
const first = root.getFirstToken();
|
||||
assert.isDefined(first);
|
||||
assert.equal(first.kind, ts.SyntaxKind.VarKeyword);
|
||||
});
|
||||
});
|
||||
describe("getLastToken", () => {
|
||||
it("gets jsdoc", () => {
|
||||
const root = ts.createSourceFile("foo.ts", "var a = true;/** comment */", ts.ScriptTarget.ES5, /*setParentNodes*/ true);
|
||||
assert.isDefined(root);
|
||||
const last = root.getLastToken();
|
||||
assert.isDefined(last);
|
||||
assert.equal(last.kind, ts.SyntaxKind.EndOfFileToken);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace ts {
|
||||
fileNames: [],
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with missing files are excluded", () => {
|
||||
@@ -231,7 +231,7 @@ namespace ts {
|
||||
fileNames: [],
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with literal excludes", () => {
|
||||
@@ -346,9 +346,9 @@ namespace ts {
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/b.ts",
|
||||
"c:/dev/node_modules/a.ts",
|
||||
"c:/dev/bower_components/a.ts",
|
||||
"c:/dev/jspm_packages/a.ts",
|
||||
"c:/dev/node_modules/a.ts"
|
||||
"c:/dev/jspm_packages/a.ts"
|
||||
],
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
@@ -373,9 +373,9 @@ namespace ts {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/node_modules/a.ts",
|
||||
"c:/dev/bower_components/a.ts",
|
||||
"c:/dev/jspm_packages/a.ts",
|
||||
"c:/dev/node_modules/a.ts"
|
||||
"c:/dev/jspm_packages/a.ts"
|
||||
],
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
@@ -398,9 +398,9 @@ namespace ts {
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/b.ts",
|
||||
"c:/dev/node_modules/a.ts",
|
||||
"c:/dev/bower_components/a.ts",
|
||||
"c:/dev/jspm_packages/a.ts",
|
||||
"c:/dev/node_modules/a.ts"
|
||||
"c:/dev/jspm_packages/a.ts"
|
||||
],
|
||||
wildcardDirectories: {},
|
||||
};
|
||||
@@ -410,6 +410,36 @@ namespace ts {
|
||||
});
|
||||
|
||||
describe("with wildcard include list", () => {
|
||||
it("is sorted in include order, then in alphabetical order", () => {
|
||||
const json = {
|
||||
include: [
|
||||
"z/*.ts",
|
||||
"x/*.ts"
|
||||
]
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/z/a.ts",
|
||||
"c:/dev/z/aba.ts",
|
||||
"c:/dev/z/abz.ts",
|
||||
"c:/dev/z/b.ts",
|
||||
"c:/dev/z/bba.ts",
|
||||
"c:/dev/z/bbz.ts",
|
||||
"c:/dev/x/a.ts",
|
||||
"c:/dev/x/aa.ts",
|
||||
"c:/dev/x/b.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev/z": ts.WatchDirectoryFlags.None,
|
||||
"c:/dev/x": ts.WatchDirectoryFlags.None
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
|
||||
it("same named declarations are excluded", () => {
|
||||
const json = {
|
||||
include: [
|
||||
@@ -506,8 +536,8 @@ namespace ts {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/x/a.ts",
|
||||
"c:/dev/x/y/a.ts",
|
||||
"c:/dev/x/a.ts",
|
||||
"c:/dev/z/a.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
@@ -554,7 +584,7 @@ namespace ts {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
},
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("always include literal files", () => {
|
||||
@@ -698,7 +728,7 @@ namespace ts {
|
||||
"c:/dev/js": ts.WatchDirectoryFlags.None
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("include .js files when allowJs=true", () => {
|
||||
@@ -816,7 +846,7 @@ namespace ts {
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("include files with .. in their name", () => {
|
||||
@@ -909,6 +939,31 @@ namespace ts {
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with jsx=react-native, allowJs=false", () => {
|
||||
const json = {
|
||||
compilerOptions: {
|
||||
jsx: "react-native",
|
||||
allowJs: false
|
||||
}
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {
|
||||
jsx: ts.JsxEmit.ReactNative,
|
||||
allowJs: false
|
||||
},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/b.tsx",
|
||||
"c:/dev/c.tsx",
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with jsx=none, allowJs=true", () => {
|
||||
const json = {
|
||||
compilerOptions: {
|
||||
@@ -961,6 +1016,33 @@ namespace ts {
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("with jsx=react-native, allowJs=true", () => {
|
||||
const json = {
|
||||
compilerOptions: {
|
||||
jsx: "react-native",
|
||||
allowJs: true
|
||||
}
|
||||
};
|
||||
const expected: ts.ParsedCommandLine = {
|
||||
options: {
|
||||
jsx: ts.JsxEmit.ReactNative,
|
||||
allowJs: true
|
||||
},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/a.ts",
|
||||
"c:/dev/b.tsx",
|
||||
"c:/dev/c.tsx",
|
||||
"c:/dev/d.js",
|
||||
"c:/dev/e.jsx",
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev": ts.WatchDirectoryFlags.Recursive
|
||||
}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("exclude .min.js files using wildcards", () => {
|
||||
const json = {
|
||||
compilerOptions: {
|
||||
@@ -1005,7 +1087,7 @@ namespace ts {
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("in excludes", () => {
|
||||
@@ -1026,7 +1108,7 @@ namespace ts {
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
});
|
||||
@@ -1047,7 +1129,7 @@ namespace ts {
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
it("in excludes", () => {
|
||||
@@ -1096,7 +1178,7 @@ namespace ts {
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
|
||||
@@ -1116,7 +1198,7 @@ namespace ts {
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
|
||||
@@ -1230,8 +1312,8 @@ namespace ts {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/.z/.b.ts",
|
||||
"c:/dev/x/.y/a.ts"
|
||||
"c:/dev/x/.y/a.ts",
|
||||
"c:/dev/.z/.b.ts"
|
||||
],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
@@ -1271,8 +1353,8 @@ namespace ts {
|
||||
options: {},
|
||||
errors: [],
|
||||
fileNames: [
|
||||
"c:/dev/.z/.b.ts",
|
||||
"c:/dev/x/.y/a.ts"
|
||||
"c:/dev/x/.y/a.ts",
|
||||
"c:/dev/.z/.b.ts"
|
||||
],
|
||||
wildcardDirectories: {
|
||||
"c:/dev/.z": ts.WatchDirectoryFlags.Recursive,
|
||||
@@ -1300,10 +1382,10 @@ namespace ts {
|
||||
fileNames: [],
|
||||
wildcardDirectories: {}
|
||||
};
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath, undefined, caseInsensitiveTsconfigPath);
|
||||
const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
|
||||
assertParsed(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,18 +144,16 @@ namespace ts {
|
||||
|
||||
const resolution = nodeModuleNameResolver("b", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile, indexFile));
|
||||
|
||||
checkResolvedModule(resolution.resolvedModule, createResolvedModule(indexPath, /*isExternalLibraryImport*/true));
|
||||
checkResolvedModule(resolution.resolvedModule, createResolvedModule(indexPath, /*isExternalLibraryImport*/ true));
|
||||
}
|
||||
}
|
||||
|
||||
it("module name as directory - handle invalid 'typings'", () => {
|
||||
testTypingsIgnored(["a", "b"]);
|
||||
testTypingsIgnored({ "a": "b" });
|
||||
testTypingsIgnored(true);
|
||||
/* tslint:disable no-null-keyword */
|
||||
testTypingsIgnored(null);
|
||||
/* tslint:enable no-null-keyword */
|
||||
testTypingsIgnored(undefined);
|
||||
testTypingsIgnored(/*typings*/ true);
|
||||
testTypingsIgnored(/*typings*/ null); // tslint:disable-line no-null-keyword
|
||||
testTypingsIgnored(/*typings*/ undefined);
|
||||
});
|
||||
it("module name as directory - load index.d.ts", () => {
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
@@ -532,7 +530,7 @@ import b = require("./moduleB");
|
||||
check("m1", main, m1);
|
||||
check("m2", main, m2);
|
||||
check("m3", main, m3Typings);
|
||||
check("m4", main, m4, /*isExternalLibraryImport*/true);
|
||||
check("m4", main, m4, /*isExternalLibraryImport*/ true);
|
||||
|
||||
function check(name: string, caller: File, expected: File, isExternalLibraryImport = false) {
|
||||
const result = resolveModuleName(name, caller.name, options, host);
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/// <reference path="..\..\compiler\emitter.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe("PrinterAPI", () => {
|
||||
function makePrintsCorrectly(prefix: string) {
|
||||
return function printsCorrectly(name: string, options: PrinterOptions, printCallback: (printer: Printer) => string) {
|
||||
it(name, () => {
|
||||
Harness.Baseline.runBaseline(`printerApi/${prefix}.${name}.js`, () =>
|
||||
printCallback(createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed, ...options })));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
describe("printFile", () => {
|
||||
const printsCorrectly = makePrintsCorrectly("printsFileCorrectly");
|
||||
const sourceFile = createSourceFile("source.ts", `
|
||||
interface A<T> {
|
||||
// comment1
|
||||
readonly prop?: T;
|
||||
|
||||
// comment2
|
||||
method(): void;
|
||||
|
||||
// comment3
|
||||
new <T>(): A<T>;
|
||||
|
||||
// comment4
|
||||
<T>(): A<T>;
|
||||
}
|
||||
|
||||
// comment5
|
||||
type B = number | string | object;
|
||||
type C = A<number> & { x: string; }; // comment6
|
||||
|
||||
// comment7
|
||||
enum E1 {
|
||||
// comment8
|
||||
first
|
||||
}
|
||||
|
||||
const enum E2 {
|
||||
second
|
||||
}
|
||||
|
||||
// comment9
|
||||
console.log(1 + 2);
|
||||
|
||||
// comment10
|
||||
function functionWithDefaultArgValue(argument: string = "defaultValue"): void { }
|
||||
`, ScriptTarget.ES2015);
|
||||
|
||||
printsCorrectly("default", {}, printer => printer.printFile(sourceFile));
|
||||
printsCorrectly("removeComments", { removeComments: true }, printer => printer.printFile(sourceFile));
|
||||
|
||||
// github #14948
|
||||
printsCorrectly("templateLiteral", {}, printer => printer.printFile(createSourceFile("source.ts", "let greeting = `Hi ${name}, how are you?`;", ScriptTarget.ES2017)));
|
||||
});
|
||||
|
||||
describe("printBundle", () => {
|
||||
const printsCorrectly = makePrintsCorrectly("printsBundleCorrectly");
|
||||
const bundle = createBundle([
|
||||
createSourceFile("a.ts", `
|
||||
/*! [a.ts] */
|
||||
|
||||
// comment0
|
||||
const a = 1;
|
||||
`, ScriptTarget.ES2015),
|
||||
createSourceFile("b.ts", `
|
||||
/*! [b.ts] */
|
||||
|
||||
// comment1
|
||||
const b = 2;
|
||||
`, ScriptTarget.ES2015)
|
||||
]);
|
||||
printsCorrectly("default", {}, printer => printer.printBundle(bundle));
|
||||
printsCorrectly("removeComments", { removeComments: true }, printer => printer.printBundle(bundle));
|
||||
});
|
||||
|
||||
describe("printNode", () => {
|
||||
const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly");
|
||||
const sourceFile = createSourceFile("source.ts", "", ScriptTarget.ES2015);
|
||||
// tslint:disable boolean-trivia
|
||||
const syntheticNode = createClassDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
/*name*/ createIdentifier("C"),
|
||||
undefined,
|
||||
undefined,
|
||||
createNodeArray([
|
||||
createProperty(
|
||||
undefined,
|
||||
createNodeArray([createToken(SyntaxKind.PublicKeyword)]),
|
||||
createIdentifier("prop"),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
])
|
||||
);
|
||||
// tslint:enable boolean-trivia
|
||||
printsCorrectly("class", {}, printer => printer.printNode(EmitHint.Unspecified, syntheticNode, sourceFile));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\harness.ts" />
|
||||
/// <reference path="..\..\harness\harnessLanguageService.ts" />
|
||||
|
||||
namespace ts {
|
||||
@@ -323,7 +323,7 @@ namespace ts {
|
||||
|
||||
const program_1 = newProgram(files, ["a.ts"], options);
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMapFromTemplate({ "b": createResolvedModule("b.ts") }));
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
checkResolvedModulesCache(program_1, "b.ts", /*expectedContent*/ undefined);
|
||||
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 2");
|
||||
@@ -332,14 +332,14 @@ namespace ts {
|
||||
|
||||
// content of resolution cache should not change
|
||||
checkResolvedModulesCache(program_1, "a.ts", createMapFromTemplate({ "b": createResolvedModule("b.ts") }));
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
checkResolvedModulesCache(program_1, "b.ts", /*expectedContent*/ undefined);
|
||||
|
||||
// imports has changed - program is not reused
|
||||
const program_3 = updateProgram(program_2, ["a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateImportsAndExports("");
|
||||
});
|
||||
assert.isTrue(!program_2.structureIsReused);
|
||||
checkResolvedModulesCache(program_3, "a.ts", undefined);
|
||||
checkResolvedModulesCache(program_3, "a.ts", /*expectedContent*/ undefined);
|
||||
|
||||
const program_4 = updateProgram(program_3, ["a.ts"], options, files => {
|
||||
const newImports = `import x from 'b'
|
||||
@@ -360,7 +360,7 @@ namespace ts {
|
||||
|
||||
const program_1 = newProgram(files, ["/a.ts"], options);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMapFromTemplate({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", undefined);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", /*expectedContent*/ undefined);
|
||||
|
||||
const program_2 = updateProgram(program_1, ["/a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 2");
|
||||
@@ -369,7 +369,7 @@ namespace ts {
|
||||
|
||||
// content of resolution cache should not change
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", createMapFromTemplate({ "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }));
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", undefined);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", /*expectedContent*/ undefined);
|
||||
|
||||
// type reference directives has changed - program is not reused
|
||||
const program_3 = updateProgram(program_2, ["/a.ts"], options, files => {
|
||||
@@ -377,7 +377,7 @@ namespace ts {
|
||||
});
|
||||
|
||||
assert.isTrue(!program_2.structureIsReused);
|
||||
checkResolvedTypeDirectivesCache(program_3, "/a.ts", undefined);
|
||||
checkResolvedTypeDirectivesCache(program_3, "/a.ts", /*expectedContent*/ undefined);
|
||||
|
||||
updateProgram(program_3, ["/a.ts"], options, files => {
|
||||
const newReferences = `/// <reference types="typedefs"/>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference path="..\..\harnessLanguageService.ts" />
|
||||
/// <reference path="..\..\harnessLanguageService.ts" />
|
||||
|
||||
interface ClassificationEntry {
|
||||
value: any;
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
{ input: "function foo () {}", rules: [ ], span: { start: 0, length: 20 }, expected: "function foo() { }" },
|
||||
{ input: "var a = (0);\r\na = (1 % 2);\r\nvar b = new Array(1, 2);\r\nfunction c(d) {\r\n try { }\r\n catch (e) { }\r\n for (f = 0; f < 10; ++f) { }\r\n for (g in h) { }\r\n if (true) {\r\n } else if (false) { }\r\n switch (i) {\r\n case (0):\r\n break;\r\n }\r\n do { } while (true);\r\n with (j) {\r\n }\r\n delete (h);\r\n void (i);\r\n}", rules: [ "SpaceAfterOpenParen", "SpaceBeforeCloseParen", "NoSpaceBetweenParens" ], span: { start: 0, length: 349 }, expected: "var a = ( 0 );\r\na = ( 1 % 2 );\r\nvar b = new Array( 1, 2 );\r\nfunction c( d ) {\r\n try { }\r\n catch ( e ) { }\r\n for ( f = 0; f < 10; ++f ) { }\r\n for ( g in h ) { }\r\n if ( true ) {\r\n } else if ( false ) { }\r\n switch ( i ) {\r\n case ( 0 ):\r\n break;\r\n }\r\n do { } while ( true );\r\n with ( j ) {\r\n }\r\n delete ( h );\r\n void ( i );\r\n}" },
|
||||
{ input: "var a = ( 0 );\r\na = ( 1 % 2 );\r\nvar b = new Array( 1, 2 );\r\nfunction c( d ) {\r\n try { }\r\n catch ( e ) { }\r\n for ( f = 0; f < 10; ++f ) { }\r\n for ( g in h ) { }\r\n if ( true ) {\r\n } else if ( false ) { }\r\n switch ( i ) {\r\n case ( 0 ):\r\n break;\r\n }\r\n do { } while ( true );\r\n with ( j ) {\r\n }\r\n delete ( h );\r\n void ( i );\r\n}", rules: [ "NoSpaceAfterOpenParen", "NoSpaceBeforeCloseParen", "NoSpaceBetweenParens" ], span: { start: 0, length: 379 }, expected: "var a = (0);\r\na = (1 % 2);\r\nvar b = new Array(1, 2);\r\nfunction c(d) {\r\n try { }\r\n catch (e) { }\r\n for (f = 0; f < 10; ++f) { }\r\n for (g in h) { }\r\n if (true) {\r\n } else if (false) { }\r\n switch (i) {\r\n case (0):\r\n break;\r\n }\r\n do { } while (true);\r\n with (j) {\r\n }\r\n delete (h);\r\n void (i);\r\n}" },
|
||||
{ input: "this . alert( \"Hello, World!\" );", rules: [ "SpaceAfterComma", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 32 }, expected: "this.alert( \"Hello, World!\" );" },
|
||||
{ input: "a\r\n;b;", rules: [ ], span: { start: 0, length: 6 }, expected: "a\r\n; b;" },
|
||||
{ input: "a\r\n; b;", rules: [ ], span: { start: 0, length: 8 }, expected: "a\r\n; b;" },
|
||||
{ input: "var a , b;\r\nf(a , b);", rules: [ ], span: { start: 0, length: 40 }, expected: "var a, b;\r\nf(a, b);" },
|
||||
{ input: "function a() {\r\n while(false)\r\n switch(b) { }\r\n\r\n for(c in d)\r\n if(c)\r\n break;\r\n\r\n do { } while(true);\r\n with(f)\r\n g = null;\r\n}", rules: [ "SpaceAfterKeywordInControl" ], span: { start: 0, length: 171 }, expected: "function a() {\r\n while (false)\r\n switch (b) { }\r\n\r\n for (c in d)\r\n if (c)\r\n break;\r\n\r\n do { } while (true);\r\n with (f)\r\n g = null;\r\n}" },
|
||||
{ input: "function a() {\r\n while (false)\r\n switch (b) { }\r\n\r\n for (c in d)\r\n if (c)\r\n break;\r\n\r\n do { } while (true);\r\n with (f)\r\n g = null;\r\n}", rules: [ "NoSpaceAfterKeywordInControl" ], span: { start: 0, length: 177 }, expected: "function a() {\r\n while(false)\r\n switch(b) { }\r\n\r\n for(c in d)\r\n if(c)\r\n break;\r\n\r\n do { } while(true);\r\n with(f)\r\n g = null;\r\n}" },
|
||||
{ input: "{\r\n(a);\r\n}", rules: [ ], span: { start: 0, length: 10 }, expected: "{\r\n (a);\r\n}" },
|
||||
{ input: "var a=[1,2];\r\nvar b=8>>2 ;\r\nvar c=1+2;", rules: [ "SpaceAfterComma", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 14, length: 12 }, expected: "var a=[1,2];\r\nvar b = 8 >> 2;\r\nvar c=1+2;" },
|
||||
{ input: "if (true) {\r\n(a);\r\n}", rules: [ ], span: { start: 0, length: 20 }, expected: "if (true) {\r\n (a);\r\n}" },
|
||||
{ input: " // var a=[1,2];\r\n /*var a=[3,4];*/\r\n /*\r\n var a=[5,6];\r\n */", rules: [ "SpaceAfterComma", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 62 }, expected: "// var a=[1,2];\r\n/*var a=[3,4];*/\r\n/*\r\n var a=[5,6];\r\n */" },
|
||||
{ input: "f ();", rules: [ ], span: { start: 0, length: 14 }, expected: "f();" },
|
||||
{ input: "var a = { b: 1 , c: 2 };\r\nvar d = [1 , 2];", rules: [ "SpaceAfterComma", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 44 }, expected: "var a = { b: 1, c: 2 };\r\nvar d = [1, 2];" },
|
||||
{ input: "if (a)\r\n if (b)\r\n if (c)\r\n c();\r\n else\r\n b();\r\n else\r\n b();\r\nelse\r\n a();", rules: [ ], span: { start: 0, length: 124 }, expected: "if (a)\r\n if (b)\r\n if (c)\r\n c();\r\n else\r\n b();\r\n else\r\n b();\r\nelse\r\n a();" },
|
||||
{ input: "function a() { };", rules: [ ], span: { start: 0, length: 20 }, expected: "function a() { };" },
|
||||
{ input: "var a =[1.2,\"JavaScript\",true,{ x: 1,y: 3 }];\r\nvar b =[[1,2],[3,4]];\r\nvar c =[1,,,,5];\r\nvar d =[\r\n [1,2],\r\n [3,4]\r\n];", rules: [ "SpaceAfterComma" ], span: { start: 0, length: 123 }, expected: "var a =[1.2, \"JavaScript\", true, { x: 1, y: 3 }];\r\nvar b =[[1, 2], [3, 4]];\r\nvar c =[1, , , , 5];\r\nvar d =[\r\n [1, 2],\r\n [3, 4]\r\n];" },
|
||||
{ input: "var a =[1.2, \"JavaScript\", true, { x: 1, y: 3 }];\r\nvar b =[[1, 2], [3, 4]];\r\nvar c =[1, , , , 5];\r\nvar d =[\r\n [1, 2],\r\n [3, 4]\r\n];", rules: [ "NoSpaceAfterComma" ], span: { start: 0, length: 136 }, expected: "var a =[1.2,\"JavaScript\",true,{ x: 1,y: 3 }];\r\nvar b =[[1,2],[3,4]];\r\nvar c =[1,,,,5];\r\nvar d =[\r\n [1,2],\r\n [3,4]\r\n];" },
|
||||
{ input: "function a(b,c) { }\r\na(0,1);\r\nvar a =[,];\r\nvar a =[0,1];\r\nvar a,b,c = 0,d = 0;\r\nfor (var a = 0,b = 10; a < 10,b >= 0; ++a,--b) { }\r\nvar a = new ActiveXObject(\"\",\"\");\r\nswitch (a) {\r\n case 1,2,3:\r\n break;\r\n}", rules: [ "SpaceAfterComma" ], span: { start: 0, length: 215 }, expected: "function a(b, c) { }\r\na(0, 1);\r\nvar a =[, ];\r\nvar a =[0, 1];\r\nvar a, b, c = 0, d = 0;\r\nfor (var a = 0, b = 10; a < 10, b >= 0; ++a, --b) { }\r\nvar a = new ActiveXObject(\"\", \"\");\r\nswitch (a) {\r\n case 1, 2, 3:\r\n break;\r\n}" },
|
||||
{ input: "function a(b, c) { }\r\na(0, 1);\r\nvar a =[, ];\r\nvar a =[0, 1];\r\nvar a, b, c = 0, d = 0;\r\nfor (var a = 0, b = 10; a < 10, b >= 0; ++a, --b) { }\r\nvar a = new ActiveXObject(\"\", \"\");\r\nswitch (a) {\r\n case 1, 2, 3:\r\n break;\r\n}", rules: [ "NoSpaceAfterComma" ], span: { start: 0, length: 228 }, expected: "function a(b,c) { }\r\na(0,1);\r\nvar a =[,];\r\nvar a =[0,1];\r\nvar a,b,c = 0,d = 0;\r\nfor (var a = 0,b = 10; a < 10,b >= 0; ++a,--b) { }\r\nvar a = new ActiveXObject(\"\",\"\");\r\nswitch (a) {\r\n case 1,2,3:\r\n break;\r\n}" },
|
||||
{ input: "function Sum(a, b, c) {\r\nvar d = 1;\r\n}", rules: [ ], span: { start: 0, length: 38 }, expected: "function Sum(a, b, c) {\r\n var d = 1;\r\n}" },
|
||||
{ input: "(function() { })();\r\nvar a = function() { };\r\nvar a = { b: function() { } };", rules: [ "SpaceAfterAnonymousFunctionKeyword" ], span: { start: 0, length: 76 }, expected: "(function () { })();\r\nvar a = function () { };\r\nvar a = { b: function () { } };" },
|
||||
{ input: "(function () { })();\r\nvar a = function () { };\r\nvar a = { b: function () { } };", rules: [ "NoSpaceAfterAnonymousFunctionKeyword" ], span: { start: 0, length: 79 }, expected: "(function() { })();\r\nvar a = function() { };\r\nvar a = { b: function() { } };" },
|
||||
{ input: "function a() {\r\n}b;", rules: [ ], span: { start: 0, length: 19 }, expected: "function a() {\r\n} b;" },
|
||||
{ input: "function a() {\r\n} b;", rules: [ ], span: { start: 0, length: 21 }, expected: "function a() {\r\n} b;" },
|
||||
{ input: "function a(){return 0;}\r\nfunction b(){toString();return 0;}", rules: [ ], span: { start: 0, length: 59 }, expected: "function a() { return 0; }\r\nfunction b() { toString(); return 0; }" },
|
||||
{ input: "for (var i = 0;i < 10;++i) { }", rules: [ "SpaceAfterSemicolonInFor" ], span: { start: 0, length: 30 }, expected: "for (var i = 0; i < 10; ++i) { }" },
|
||||
{ input: "for (var i = 0; i < 10; ++i) { }", rules: [ "NoSpaceAfterSemicolonInFor" ], span: { start: 0, length: 32 }, expected: "for (var i = 0;i < 10;++i) { }" },
|
||||
{ input: "function f() {\r\nif (1)\r\n{\r\nvar a=0;\r\n}\r\n}", rules: [ "SpaceBeforeOpenCurlyInControl", "NewLineBeforeOpenCurlyInFunction" ], span: { start: 0, length: 41 }, expected: "function f()\n{\r\n if (1) {\r\n var a=0;\r\n }\r\n}" },
|
||||
{ input: "function a(b) {\r\n a({\r\n});\r\n}", rules: [ ], span: { start: 0, length: 32 }, expected: "function a(b) {\r\n a({\r\n });\r\n}" },
|
||||
{ input: "// var a=[1,2];\r\n/*\r\nvar a=[1,2];\r\n*/", rules: [ "SpaceAfterComma", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 3, length: 12 }, expected: "// var a=[1,2];\r\n/*\r\nvar a=[1,2];\r\n*/" },
|
||||
{ input: "// var a=[1,2];\r\n/*\r\nvar a=[1,2];\r\n*/", rules: [ "SpaceAfterComma", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 21, length: 12 }, expected: "// var a=[1,2];\r\n/*\r\nvar a=[1,2];\r\n*/" },
|
||||
{ input: "eval(\"var a=b[1,2+3];\");", rules: [ "SpaceAfterComma", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 6, length: 15 }, expected: "eval(\"var a=b[1,2+3];\");" },
|
||||
{ input: "0 + +1;\r\n0 + +a;\r\n0 + +(1);\r\n0 + +(+1);\r\n0 + +[1];\r\n0 + +[+1];\r\n0 + +this.a;\r\n0 + +new Number(+1);\r\n\r\n0 - -1;\r\n0 - -a;\r\n0 - -(1);\r\n0 - -(-1);\r\n0 - -[1];\r\n0 - -[-1];\r\n0 - -this.a;\r\n0 - -new Number(-1);\r\n\r\n0 + ~1;\r\n0 - ~a;\r\n0 + ~(1);\r\n0 - ~(~1);\r\n0 + ~[1];\r\n0 - ~[~1];\r\n0 + ~this.a;\r\n0 - ~new Number(~1);\r\n\r\n0 - !1;\r\n0 + !a;\r\n0 - !(1);\r\n0 + !(!1);\r\n0 - ![1];\r\n0 + ![!1];\r\n0 - !this.a;\r\n0 + !new Number(!1);", rules: [ "NoSpaceBeforeBinaryOperator", "NoSpaceAfterBinaryOperator" ], span: { start: 0, length: 404 }, expected: "0+ +1;\r\n0+ +a;\r\n0+ +(1);\r\n0+ +(+1);\r\n0+ +[1];\r\n0+ +[+1];\r\n0+ +this.a;\r\n0+ +new Number(+1);\r\n\r\n0- -1;\r\n0- -a;\r\n0- -(1);\r\n0- -(-1);\r\n0- -[1];\r\n0- -[-1];\r\n0- -this.a;\r\n0- -new Number(-1);\r\n\r\n0+~1;\r\n0-~a;\r\n0+~(1);\r\n0-~(~1);\r\n0+~[1];\r\n0-~[~1];\r\n0+~this.a;\r\n0-~new Number(~1);\r\n\r\n0-!1;\r\n0+!a;\r\n0-!(1);\r\n0+!(!1);\r\n0-![1];\r\n0+![!1];\r\n0-!this.a;\r\n0+!new Number(!1);" },
|
||||
{ input: "0+ +1;\r\n0+ +a;\r\n0+ +(1);\r\n0+ +(+1);\r\n0+ +[1];\r\n0+ +[+1];\r\n0+ +this.a;\r\n0+ +new Number(+1);\r\n\r\n0- -1;\r\n0- -a;\r\n0- -(1);\r\n0- -(-1);\r\n0- -[1];\r\n0- -[-1];\r\n0- -this.a;\r\n0- -new Number(-1);\r\n\r\n0+~1;\r\n0-~a;\r\n0+~(1);\r\n0-~(~1);\r\n0+~[1];\r\n0-~[~1];\r\n0+~this.a;\r\n0-~new Number(~1);\r\n\r\n0-!1;\r\n0+!a;\r\n0-!(1);\r\n0+!(!1);\r\n0-![1];\r\n0+![!1];\r\n0-!this.a;\r\n0+!new Number(!1);", rules: [ "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 356 }, expected: "0 + +1;\r\n0 + +a;\r\n0 + +(1);\r\n0 + +(+1);\r\n0 + +[1];\r\n0 + +[+1];\r\n0 + +this.a;\r\n0 + +new Number(+1);\r\n\r\n0 - -1;\r\n0 - -a;\r\n0 - -(1);\r\n0 - -(-1);\r\n0 - -[1];\r\n0 - -[-1];\r\n0 - -this.a;\r\n0 - -new Number(-1);\r\n\r\n0 + ~1;\r\n0 - ~a;\r\n0 + ~(1);\r\n0 - ~(~1);\r\n0 + ~[1];\r\n0 - ~[~1];\r\n0 + ~this.a;\r\n0 - ~new Number(~1);\r\n\r\n0 - !1;\r\n0 + !a;\r\n0 - !(1);\r\n0 + !(!1);\r\n0 - ![1];\r\n0 + ![!1];\r\n0 - !this.a;\r\n0 + !new Number(!1);" },
|
||||
{ input: "for (var a = 0; a < 2; ++a) {\r\n}", rules: [ "NewLineBeforeOpenCurlyInControl", "SpaceAfterSemicolonInFor" ], span: { start: 0, length: 32 }, expected: "for (var a = 0; a < 2; ++a)\n{\r\n}" },
|
||||
{ input: "for (var a = 0; a < 2; ++a)\n{\r\n}", rules: [ "SpaceBeforeOpenCurlyInControl", "SpaceAfterSemicolonInFor" ], span: { start: 0, length: 32 }, expected: "for (var a = 0; a < 2; ++a) {\r\n}" },
|
||||
{ input: "function foo(a, b, c) { a = b + c;\n}", rules: [ "NewLineBeforeOpenCurlyInFunction", "NewLineAfterOpenCurlyInBlockContext", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 36 }, expected: "function foo(a, b, c)\n{\n a = b + c;\n}" },
|
||||
{ input: "function a() {\r\n // comment\r\n}", rules: [ ], span: { start: 0, length: 33 }, expected: "function a() {\r\n // comment\r\n}" },
|
||||
{ input: "if (false) {\r\n} else if (true) {\r\n} else {\r\n}", rules: [ "NewLineBeforeOpenCurlyInControl" ], span: { start: 0, length: 45 }, expected: "if (false)\n{\r\n} else if (true)\n{\r\n} else\n{\r\n}" },
|
||||
{ input: "if (false)\n{\r\n} else if (true)\n{\r\n} else\n{\r\n}", rules: [ "SpaceBeforeOpenCurlyInControl" ], span: { start: 0, length: 45 }, expected: "if (false) {\r\n} else if (true) {\r\n} else {\r\n}" },
|
||||
{ input: "var a = (0);\r\nvar b = (1);\r\nvar c = (1 + 2);\r\nvar d = ((1 + 2)-(3 + 4));\r\n\r\nvar e = ( 0 );\r\nvar f = ( 1 );\r\nvar g = ( 1 + 2 );\r\nvar h = ( ( 1 + 2 ) - ( 3 + 4 ) );", rules: [ "SpaceAfterOpenParen", "SpaceBeforeCloseParen", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 162 }, expected: "var a = ( 0 );\r\nvar b = ( 1 );\r\nvar c = ( 1 + 2 );\r\nvar d = ( ( 1 + 2 ) - ( 3 + 4 ) );\r\n\r\nvar e = ( 0 );\r\nvar f = ( 1 );\r\nvar g = ( 1 + 2 );\r\nvar h = ( ( 1 + 2 ) - ( 3 + 4 ) );" },
|
||||
{ input: "eval(\"var a=b[1,2+3];\");", rules: [ "SpaceAfterComma", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 24 }, expected: "eval(\"var a=b[1,2+3];\");" },
|
||||
{ input: "for (a in b)\r\n\r\n{ i++; }\r\n\r\nfor (a in b)\r\n\r\n{\r\ni++; }", rules: [ "SpaceBeforeOpenCurlyInControl" ], span: { start: 0, length: 53 }, expected: "for (a in b)\r\n\r\n{ i++; }\r\n\r\nfor (a in b) {\r\n i++;\n}" },
|
||||
{ input: "for (a in b) {\r\n}", rules: [ "NewLineBeforeOpenCurlyInControl" ], span: { start: 0, length: 17 }, expected: "for (a in b)\n{\r\n}" },
|
||||
{ input: "for (a in b)\n{\r\n}", rules: [ "SpaceBeforeOpenCurlyInControl" ], span: { start: 0, length: 17 }, expected: "for (a in b) {\r\n}" },
|
||||
{ input: " var a = { } ; \r\nvar b = { c : d, e : { } };\r\n ", rules: [ "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 59 }, expected: "var a = {};\r\nvar b = { c: d, e: {} };\r\n" },
|
||||
{ input: "while (true) { }", rules: [ ], span: { start: 0, length: 19 }, expected: "while (true) { }" },
|
||||
{ input: "for (a in b){ i++; }\r\n\r\nfor (a in b){ i++; }", rules: [ "SpaceBeforeOpenCurlyInControl" ], span: { start: 0, length: 44 }, expected: "for (a in b) { i++; }\r\n\r\nfor (a in b) { i++; }" },
|
||||
{ input: "function a() {\r\n}", rules: [ "NewLineBeforeOpenCurlyInFunction" ], span: { start: 0, length: 17 }, expected: "function a()\n{\r\n}" },
|
||||
{ input: "function a()\n{\r\n}", rules: [ "SpaceBeforeOpenCurlyInFunction" ], span: { start: 0, length: 17 }, expected: "function a() {\r\n}" },
|
||||
{ input: "a;\r\nb;c;\r\nd;", rules: [ ], span: { start: 0, length: 12 }, expected: "a;\r\nb; c;\r\nd;" },
|
||||
{ input: "a;\r\nb; c;\r\nd;", rules: [ ], span: { start: 0, length: 14 }, expected: "a;\r\nb; c;\r\nd;" },
|
||||
{ input: " var a = 0;\r\n function b() {\r\n var c = 0;\r\n }", rules: [ "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 61 }, expected: "var a = 0;\r\nfunction b() {\r\n var c = 0;\r\n}" },
|
||||
{ input: "a;b;", rules: [ ], span: { start: 0, length: 4 }, expected: "a; b;" },
|
||||
{ input: "a; b;", rules: [ ], span: { start: 0, length: 6 }, expected: "a; b;" },
|
||||
{ input: "var a = (0);\r\nvar b = (1);\r\nvar c = (1 + 2);\r\nvar d = ((1 + 2)-(3 + 4));\r\n\r\nvar e = ( 0 );\r\nvar f = ( 1 );\r\nvar g = ( 1 + 2 );\r\nvar h = ( ( 1 + 2 ) - ( 3 + 4 ) );", rules: [ "NoSpaceAfterOpenParen", "NoSpaceBeforeCloseParen", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 162 }, expected: "var a = (0);\r\nvar b = (1);\r\nvar c = (1 + 2);\r\nvar d = ((1 + 2) - (3 + 4));\r\n\r\nvar e = (0);\r\nvar f = (1);\r\nvar g = (1 + 2);\r\nvar h = ((1 + 2) - (3 + 4));" },
|
||||
{ input: "function a() {\r\n(b);\r\n}", rules: [ ], span: { start: 0, length: 23 }, expected: "function a() {\r\n (b);\r\n}" },
|
||||
{ input: "function test(a) {\n var i;\n for (i = 0;i < 1; i++){ //select\n a++;//select\n }\n}", rules: [ "NewLineBeforeOpenCurlyInControl", "NewLineAfterOpenCurlyInBlockContext", "NewLineBeforeOpenCurlyInFunction", "SpaceAfterSemicolonInFor" ], span: { start: 30, length: 50 }, expected: "function test(a) {\n var i;\n for (i = 0; i < 1; i++)\n { //select\n a++;//select\n }\n}" },
|
||||
{ input: "function a(){ return 1; }", rules: [ "SpaceBeforeOpenCurlyInFunction" ], span: { start: 0, length: 25 }, expected: "function a() { return 1; }" },
|
||||
{ input: "do {\r\n} while (true);", rules: [ "NewLineBeforeOpenCurlyInControl" ], span: { start: 0, length: 21 }, expected: "do\n{\r\n} while (true);" },
|
||||
{ input: "do\n{\r\n} while (true);", rules: [ "SpaceBeforeOpenCurlyInControl" ], span: { start: 0, length: 21 }, expected: "do {\r\n} while (true);" },
|
||||
{ input: "for (;;) { a = b + c; b = 2;\n}", rules: [ "NewLineBeforeOpenCurlyInControl", "NewLineAfterOpenCurlyInBlockContext", "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator", "NoSpaceAfterSemicolonInFor" ], span: { start: 0, length: 30 }, expected: "for (;;)\n{\n a = b + c; b = 2;\n}" },
|
||||
{ input: "var a =0;\r\n\r\n+ 1;\r\n+ a;\r\n+ (1);\r\n+ (+ 1);\r\n+ [1];\r\n+ [+ 1];\r\n+ this.a;\r\n+ new Number(+ 1);\r\n\r\n- 1;\r\n- a;\r\n- (1);\r\n- (- 1);\r\n- [1];\r\n- [- 1];\r\n- this.a;\r\n- new Number(- 1);\r\n\r\n~ 1;\r\n~ a;\r\n~ (1);\r\n~ (~ 1);\r\n~ [1];\r\n~ [~ 1];\r\n~ this.a;\r\n~ new Number(~ 1);\r\n\r\n! 1;\r\n! a;\r\n! (1);\r\n! (! 1);\r\n! [1];\r\n! [! 1];\r\n! this.a;\r\n! new Number(! 1);\r\n\r\n++ a;\r\n++ (a);\r\n++ this.a;\r\n++ new f().a;\r\n\r\n-- a;\r\n-- (a);\r\n-- this.a;\r\n-- new f().a;\r\n\r\na ++;\r\n(a) ++;\r\nthis.a ++;\r\nnew f().a ++;\r\n\r\na --;\r\n(a) --;\r\nthis.a --;\r\nnew f().a --;", rules: [ ], span: { start: 0, length: 513 }, expected: "var a =0;\r\n\r\n+1;\r\n+a;\r\n+(1);\r\n+(+1);\r\n+[1];\r\n+[+1];\r\n+this.a;\r\n+new Number(+1);\r\n\r\n-1;\r\n-a;\r\n-(1);\r\n-(-1);\r\n-[1];\r\n-[-1];\r\n-this.a;\r\n-new Number(-1);\r\n\r\n~1;\r\n~a;\r\n~(1);\r\n~(~1);\r\n~[1];\r\n~[~1];\r\n~this.a;\r\n~new Number(~1);\r\n\r\n!1;\r\n!a;\r\n!(1);\r\n!(!1);\r\n![1];\r\n![!1];\r\n!this.a;\r\n!new Number(!1);\r\n\r\n++a;\r\n++(a);\r\n++this.a;\r\n++new f().a;\r\n\r\n--a;\r\n--(a);\r\n--this.a;\r\n--new f().a;\r\n\r\na++;\r\n(a)++;\r\nthis.a++;\r\nnew f().a++;\r\n\r\na--;\r\n(a)--;\r\nthis.a--;\r\nnew f().a--;" },
|
||||
{ input: "switch (a) {\r\n case 0:\r\n break;\r\n default:\r\n break;\r\n}", rules: [ "NewLineBeforeOpenCurlyInControl" ], span: { start: 0, length: 74 }, expected: "switch (a)\n{\r\n case 0:\r\n break;\r\n default:\r\n break;\r\n}" },
|
||||
{ input: "switch (a)\n{\r\n case 0:\r\n break;\r\n default:\r\n break;\r\n}", rules: [ "SpaceBeforeOpenCurlyInControl" ], span: { start: 0, length: 74 }, expected: "switch (a) {\r\n case 0:\r\n break;\r\n default:\r\n break;\r\n}" },
|
||||
{ input: "function a()\r\n\r\n\r\n{\r\n}", rules: [ "SpaceBeforeOpenCurlyInFunction" ], span: { start: 0, length: 22 }, expected: "function a() {\r\n}" },
|
||||
{ input: "try {\r\n} catch (e) {\r\n} finally {\r\n}", rules: [ "NewLineBeforeOpenCurlyInControl" ], span: { start: 0, length: 36 }, expected: "try\n{\r\n} catch (e)\n{\r\n} finally\n{\r\n}" },
|
||||
{ input: "try\n{\r\n} catch (e)\n{\r\n} finally\n{\r\n}", rules: [ "SpaceBeforeOpenCurlyInControl" ], span: { start: 0, length: 36 }, expected: "try {\r\n} catch (e) {\r\n} finally {\r\n}" },
|
||||
{ input: "with (a) {\r\n b = 0;\r\n}", rules: [ "NewLineBeforeOpenCurlyInControl" ], span: { start: 0, length: 25 }, expected: "with (a)\n{\r\n b = 0;\r\n}" },
|
||||
{ input: "with (a)\n{\r\n b = 0;\r\n}", rules: [ "SpaceBeforeOpenCurlyInControl" ], span: { start: 0, length: 25 }, expected: "with (a) {\r\n b = 0;\r\n}" },
|
||||
{ input: "var a=0+1-2*3/4%5;\r\na+=6;\r\na-=7;\r\na*=7;\r\na/=8;\r\na%=9;\r\na=+1- -2+ +3;\r\na=1.0+2.+.0;\r\n++a+a++;\r\n--a-a--;\r\n\r\nvar b=~1&2|3^4<<1>>1>>>2;\r\nb&=5;\r\nb^=6;\r\nb|=7;\r\nb<<=8;\r\nb>>=9;\r\nb>>>=10;\r\n\r\nvar c=a>b;\r\nc=b<a?a:b;\r\nc=true&&false||true;\r\nc=a==b;\r\nc=a===b;\r\nc=a!=b;\r\nc=a!==b;\r\nc=a<=b;\r\nc=a>=b;\r\nc=!c;\r\n\r\n++a+ ++a+a++ +a++ + ++a;\r\n--a- --a-a-- -a-- - --a;\r\n\r\nfunction d::e() { }", rules: [ "SpaceBeforeBinaryOperator", "SpaceAfterBinaryOperator" ], span: { start: 0, length: 366 }, expected: "var a = 0 + 1 - 2 * 3 / 4 % 5;\r\na += 6;\r\na -= 7;\r\na *= 7;\r\na /= 8;\r\na %= 9;\r\na = +1 - -2 + +3;\r\na = 1.0 + 2. + .0;\r\n++a + a++;\r\n--a - a--;\r\n\r\nvar b = ~1 & 2 | 3 ^ 4 << 1 >> 1 >>> 2;\r\nb &= 5;\r\nb ^= 6;\r\nb |= 7;\r\nb <<= 8;\r\nb >>= 9;\r\nb >>>= 10;\r\n\r\nvar c = a > b;\r\nc = b < a ? a : b;\r\nc = true && false || true;\r\nc = a == b;\r\nc = a === b;\r\nc = a != b;\r\nc = a !== b;\r\nc = a <= b;\r\nc = a >= b;\r\nc = !c;\r\n\r\n++a + ++a + a++ + a++ + ++a;\r\n--a - --a - a-- - a-- - --a;\r\n\r\nfunction d::e() { }" },
|
||||
{ input: "var a = 0 + 1 - 2 * 3 / 4 % 5;\r\na += 6;\r\na -= 7;\r\na *= 7;\r\na /= 8;\r\na %= 9;\r\na = +1 - -2 + +3;\r\na = 1.0 + 2. + .0;\r\n++a + a++;\r\n--a - a--;\r\n\r\nvar b = ~1 & 2 | 3 ^ 4 << 1 >> 1 >>> 2;\r\nb &= 5;\r\nb ^= 6;\r\nb |= 7;\r\nb <<= 8;\r\nb >>= 9;\r\nb >>>= 10;\r\n\r\nvar c = a > b;\r\nc = b < a ? a : b;\r\nc = true && false || true;\r\nc = a == b;\r\nc = a === b;\r\nc = a != b;\r\nc = a !== b;\r\nc = a <= b;\r\nc = a >= b;\r\nc = !c;\r\n\r\n++a + ++a + a++ + a++ + ++a;\r\n--a - --a - a-- - a-- - --a;\r\n\r\nfunction d::e() { }", rules: [ "NoSpaceBeforeBinaryOperator", "NoSpaceAfterBinaryOperator" ], span: { start: 0, length: 480 }, expected: "var a=0+1-2*3/4%5;\r\na+=6;\r\na-=7;\r\na*=7;\r\na/=8;\r\na%=9;\r\na=+1- -2+ +3;\r\na=1.0+2.+.0;\r\n++a+a++;\r\n--a-a--;\r\n\r\nvar b=~1&2|3^4<<1>>1>>>2;\r\nb&=5;\r\nb^=6;\r\nb|=7;\r\nb<<=8;\r\nb>>=9;\r\nb>>>=10;\r\n\r\nvar c=a>b;\r\nc=b<a?a:b;\r\nc=true&&false||true;\r\nc=a==b;\r\nc=a===b;\r\nc=a!=b;\r\nc=a!==b;\r\nc=a<=b;\r\nc=a>=b;\r\nc=!c;\r\n\r\n++a+ ++a+a++ +a++ + ++a;\r\n--a- --a-a-- -a-- - --a;\r\n\r\nfunction d::e() { }" },
|
||||
{ input: "function foo()\n\n{ a = 1\n}", rules: [ "NewLineBeforeOpenCurlyInFunction" ], span: { start: 0, length: 25 }, expected: "function foo()\n{\n a = 1\n}" },
|
||||
{ input: "while (true) {\r\n}", rules: [ "NewLineBeforeOpenCurlyInControl" ], span: { start: 0, length: 17 }, expected: "while (true)\n{\r\n}" },
|
||||
{ input: "while (true)\n{\r\n}", rules: [ "SpaceBeforeOpenCurlyInControl" ], span: { start: 0, length: 17 }, expected: "while (true) {\r\n}" },
|
||||
{ input: "var z = 1;\r\n for (i = 0; i < 10; i++)\r\n for (j = 0; j < 10; j++)\r\nfor (k = 0; k < 10; ++k)\r\n{\r\nz++;\r\n}", rules: [ "SpaceBeforeOpenCurlyInControl", "SpaceAfterSemicolonInFor" ], span: { start: 0, length: 117 }, expected: "var z = 1;\r\nfor (i = 0; i < 10; i++)\r\n for (j = 0; j < 10; j++)\r\n for (k = 0; k < 10; ++k) {\r\n z++;\r\n }" },
|
||||
{ input: "a++;b++;\nfor (; ; ) {\nx++;m++;\n}", rules: [ "SpaceAfterSemicolonInFor" ], span: { start: 0, length: 32 }, expected: "a++; b++;\nfor (; ; ) {\n x++; m++;\n}" },
|
||||
{ input: "var a;\r\n $(document).ready(function() {\r\n alert('hello');\r\n});\r\n", rules: [ ], span: { start: 0, length: 117 }, expected: "var a;\r\n$(document).ready(function () {\r\n alert('hello');\r\n});\r\n" }
|
||||
@@ -1,66 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
.code
|
||||
{
|
||||
font-family: Lucida Console;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
border: solid black 1px;
|
||||
margin-bottom: 2em;
|
||||
background: #F5F5F5;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
th
|
||||
{
|
||||
text-align: left;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
vertical-align: top;
|
||||
padding: 0.75em;
|
||||
margin: 0.25em;
|
||||
}
|
||||
|
||||
td.test-input
|
||||
{
|
||||
background: #DDE;
|
||||
}
|
||||
|
||||
td.test-output
|
||||
{
|
||||
background: #FEE;
|
||||
}
|
||||
|
||||
td.test-expected
|
||||
{
|
||||
background: #EFE;
|
||||
}
|
||||
|
||||
td.test-operation
|
||||
{
|
||||
font-family: inherit;
|
||||
padding: 0.1em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
function copy(code) {
|
||||
if (window.clipboardData) {
|
||||
window.clipboardData.setData('Text', decodeURIComponent(code));
|
||||
} else {
|
||||
alert(code);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -1,88 +0,0 @@
|
||||
///<reference path='_project.ts'/>
|
||||
|
||||
describe('getFormattingEditsForRange', function() {
|
||||
//
|
||||
// Verify that formatting the typescript file "sourceFileName" results in the
|
||||
// baseline file "baselineFileName".
|
||||
//
|
||||
function getFormattingEditsForRange(sourceFileName: string) {
|
||||
var baselineFileName = "tests/cases/unittests/services/testCode/formatting/" + sourceFileName + "BaseLine.ts";
|
||||
sourceFileName = "tests/cases/unittests/services/testCode/formatting/" + sourceFileName + ".ts";
|
||||
|
||||
var typescriptLS = new Harness.TypeScriptLS();
|
||||
typescriptLS.addDefaultLibrary();
|
||||
typescriptLS.addFile(sourceFileName);
|
||||
|
||||
var ls = typescriptLS.getLanguageService();
|
||||
var script = ls.languageService.getScriptAST(sourceFileName);
|
||||
assert.notNull(script);
|
||||
|
||||
var edits = ls.languageService.getFormattingEditsForRange(sourceFileName, 0, script.limChar, new Services.FormatCodeOptions());
|
||||
typescriptLS.checkEdits(sourceFileName, baselineFileName, edits);
|
||||
}
|
||||
|
||||
describe('test cases for formatting engine', function() {
|
||||
it("formats typescript constructs properly", function() {
|
||||
getFormattingEditsForRange('typescriptConstructs');
|
||||
});
|
||||
it("formats document ready function properly", function() {
|
||||
getFormattingEditsForRange('documentReadyFunction');
|
||||
});
|
||||
it("formats on closing bracket properly", function() {
|
||||
getFormattingEditsForRange('onClosingBracket');
|
||||
});
|
||||
it("formats various javascript constructs", function() {
|
||||
getFormattingEditsForRange('various');
|
||||
});
|
||||
it("formats main javascript program", function() {
|
||||
getFormattingEditsForRange('main');
|
||||
});
|
||||
it("formats on semicolon properly", function() {
|
||||
getFormattingEditsForRange('onSemiColon');
|
||||
});
|
||||
it("formats enum with trailling tab characters properly", function() {
|
||||
getFormattingEditsForRange('tabAfterCloseCurly');
|
||||
});
|
||||
it("formats object literal", function() {
|
||||
getFormattingEditsForRange('objectLiteral');
|
||||
});
|
||||
it("formats with statements", function() {
|
||||
getFormattingEditsForRange('withStatement');
|
||||
});
|
||||
it("formats ':' and '?' in parameters", function() {
|
||||
getFormattingEditsForRange('colonAndQMark');
|
||||
});
|
||||
it("formats 'import' declaration", function() {
|
||||
getFormattingEditsForRange('importDeclaration');
|
||||
});
|
||||
it("formats exported class with implicit module", function() {
|
||||
//TODO: this is to force generation of implicit module in AST
|
||||
var svGenTarget = TypeScript.moduleGenTarget;
|
||||
try {
|
||||
TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Asynchronous;
|
||||
getFormattingEditsForRange('implicitModule');
|
||||
}
|
||||
finally {
|
||||
TypeScript.moduleGenTarget = svGenTarget;
|
||||
}
|
||||
});
|
||||
it("formats constructor statements correctelly", function() {
|
||||
getFormattingEditsForRange('spaceAfterConstructor');
|
||||
});
|
||||
it("formats classes and interfaces correctelly", function() {
|
||||
getFormattingEditsForRange('classes');
|
||||
});
|
||||
it("formats modules correctly", function() {
|
||||
getFormattingEditsForRange('modules');
|
||||
});
|
||||
it("formats fat arrow expressions correctelly", function() {
|
||||
getFormattingEditsForRange('fatArrowFunctions');
|
||||
});
|
||||
it("formats empty object/interface literals correctelly", function() {
|
||||
getFormattingEditsForRange('emptyInterfaceLiteral');
|
||||
});
|
||||
it("formats variable declaration lists", function() {
|
||||
getFormattingEditsForRange('formatVariableDeclarationList');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,410 +0,0 @@
|
||||
///<reference path='_project.ts'/>
|
||||
|
||||
describe('getSmartIndentAtLineNumber', function() {
|
||||
var typescriptLS = new Harness.TypeScriptLS();
|
||||
|
||||
typescriptLS.addDefaultLibrary();
|
||||
|
||||
var fileName = 'tests/cases/unittests/services/testCode/getSmartIndentAtLineNumber.ts';
|
||||
var fileName2 = 'tests/cases/unittests/services/testCode/getSmartIndentAtLineNumber2.ts';
|
||||
var fileName3 = 'tests/cases/unittests/services/testCode/getSmartIndentAtLineNumber3.ts';
|
||||
|
||||
typescriptLS.addFile(fileName);
|
||||
typescriptLS.addFile(fileName2);
|
||||
typescriptLS.addFile(fileName3);
|
||||
|
||||
var ls = typescriptLS.getLanguageService();
|
||||
|
||||
//
|
||||
// line is 1-based
|
||||
//
|
||||
function getSmartIndent(fileName: string, line: number): number {
|
||||
assert.is(line >= 1);
|
||||
var options = new Services.EditorOptions();
|
||||
var position = typescriptLS.lineColToPosition(fileName, line, 1);
|
||||
return ls.languageService.getSmartIndentAtLineNumber(fileName, position, options);
|
||||
}
|
||||
|
||||
describe("test cases for smart indent", function() {
|
||||
|
||||
it("smart indent inside module", function() {
|
||||
var result = getSmartIndent(fileName, 2);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent inside class", function() {
|
||||
var result = getSmartIndent(fileName, 4);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after property in class", function() {
|
||||
var result = getSmartIndent(fileName, 6);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent inside method in class ", function() {
|
||||
var result = getSmartIndent(fileName, 9);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(12, result);
|
||||
});
|
||||
|
||||
it("smart indent after after method in class", function() {
|
||||
var result = getSmartIndent(fileName, 12);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after class", function() {
|
||||
var result = getSmartIndent(fileName, 17);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent in interface", function() {
|
||||
var result = getSmartIndent(fileName, 19);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after property in interface", function() {
|
||||
var result = getSmartIndent(fileName, 21);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after method in interface", function() {
|
||||
var result = getSmartIndent(fileName, 23);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after interface", function() {
|
||||
var result = getSmartIndent(fileName, 25);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent in nested module", function() {
|
||||
var result = getSmartIndent(fileName, 27);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after function in nested module", function() {
|
||||
var result = getSmartIndent(fileName, 30);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after variable in nested module", function() {
|
||||
var result = getSmartIndent(fileName, 32);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after nested module", function() {
|
||||
var result = getSmartIndent(fileName, 34);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent in enum", function() {
|
||||
var result = getSmartIndent(fileName, 36);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after variable in enum", function() {
|
||||
var result = getSmartIndent(fileName, 38);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after 2nd variable in enum", function() {
|
||||
var result = getSmartIndent(fileName, 40);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after enum", function() {
|
||||
var result = getSmartIndent(fileName, 42);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent after module", function() {
|
||||
var result = getSmartIndent(fileName, 44);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(0, result);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
it("smart indent after an aligned function argument", function() {
|
||||
var result = getSmartIndent(fileName, 47);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(13, result);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
it("smart indent inside a 'for' statement", function() {
|
||||
var result = getSmartIndent(fileName, 53);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after a 'for' statement", function() {
|
||||
var result = getSmartIndent(fileName, 55);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent inside a 'for in' statement", function() {
|
||||
var result = getSmartIndent(fileName, 57);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after a 'for in' statement", function() {
|
||||
var result = getSmartIndent(fileName, 59);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent inside a 'with' statement", function() {
|
||||
var result = getSmartIndent(fileName, 61);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after a 'with' statement", function() {
|
||||
var result = getSmartIndent(fileName, 63);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent inside a 'switch' statement", function() {
|
||||
var result = getSmartIndent(fileName, 65);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after a 'switch' statement", function() {
|
||||
var result = getSmartIndent(fileName, 67);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent inside a 'break' statement", function() {
|
||||
var result = getSmartIndent(fileName, 69);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after a 'break' statement", function() {
|
||||
var result = getSmartIndent(fileName, 71);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(12, result);
|
||||
});
|
||||
|
||||
it("smart indent after a 'break' statement", function() {
|
||||
var result = getSmartIndent(fileName, 73);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after last 'switch' statement", function() {
|
||||
var result = getSmartIndent(fileName, 75);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
it("smart indent before 'try' in 'try/catch' statement", function() {
|
||||
var result = getSmartIndent(fileName, 79);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent insde 'try' in 'try/catch' statement", function() {
|
||||
var result = getSmartIndent(fileName, 81);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent before 'catch' in 'try/catch' statement", function() {
|
||||
var result = getSmartIndent(fileName, 83);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent inside 'catch' in 'try/catch' statement", function() {
|
||||
var result = getSmartIndent(fileName, 85);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after 'catch' in 'try/catch' statement", function() {
|
||||
var result = getSmartIndent(fileName, 87);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
it("smart indent before 'try' in 'try/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 92);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent insde 'try' in 'try/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 94);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent before 'finally' in 'try/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 96);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent inside 'finally' in 'try/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 98);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after 'finally' in 'try/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 100);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
it("smart indent before 'try' in 'try/catch/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 104);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent insde 'try' in 'try/catch/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 106);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent before 'catch' in 'try/catch/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 108);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent inside 'catch' in 'try/catch/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 110);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent before 'finally' in 'try/catch/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 112);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
it("smart indent inside 'finally' in 'try/catch/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 114);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(8, result);
|
||||
});
|
||||
|
||||
it("smart indent after 'finally' in 'try/catch/finally' statement", function() {
|
||||
var result = getSmartIndent(fileName, 116);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
it("smart indent inside a block inside case", function() {
|
||||
var result = getSmartIndent(fileName, 127);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(20, result);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
it("smart indent works for a non terminated argument list at the end of a file", function() {
|
||||
var result = getSmartIndent(fileName2, 8);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
it("smart indent works for a non terminated if statement at the end of a file", function() {
|
||||
var result = getSmartIndent(fileName3, 7);
|
||||
|
||||
assert.notNull(result);
|
||||
assert.equal(4, result);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,212 +0,0 @@
|
||||
/// <reference path='..\..\..\..\src\harness\harness.ts'/>
|
||||
/// <reference path="..\..\..\..\src\services\formatting\formatting.ts"/>
|
||||
|
||||
interface DocumentTestJson {
|
||||
input: string;
|
||||
rules: string[];
|
||||
span: { start: number; length: number; };
|
||||
expected: string;
|
||||
}
|
||||
|
||||
interface FormatOperationTestJson {
|
||||
input: string;
|
||||
operations: {
|
||||
operation: string;
|
||||
point: { position: number; };
|
||||
span: { start: number; length: number; };
|
||||
}[];
|
||||
expected: string;
|
||||
}
|
||||
|
||||
function markupCodeForHtml(code: string) {
|
||||
var formatted = code.replace(/</g, '<').replace(/ /g, '·').replace(/\t/g, ' → ').replace(/\n/g,'↵<br>');
|
||||
var escaped = encodeURIComponent(code).replace(/'/g, '%27');
|
||||
|
||||
return formatted + '<br><a href="javascript:;" onclick="copy(\'' + escaped + '\');">Copy</a>';
|
||||
}
|
||||
|
||||
describe('importedJavaScriptFormatting - formatting rules', function() {
|
||||
var documentTests: DocumentTestJson[] = eval('[' + IO.readFile(Harness.userSpecifiedroot + 'tests/cases/unittests/services/documentFormattingTests.json').contents() + ']');
|
||||
|
||||
var outputFile = 'diff-1.html';
|
||||
IO.writeFile(outputFile, IO.readFile(Harness.userSpecifiedroot + 'tests/cases/unittests/services/formatDiffTemplate.html').contents(), false);
|
||||
|
||||
var checkTest = function(test: DocumentTestJson) {
|
||||
var filename = 'temp.ts';
|
||||
var typescriptLS = new Harness.TypeScriptLS();
|
||||
typescriptLS.addScript(filename, test.input);
|
||||
|
||||
var ls = typescriptLS.getLanguageService().languageService;
|
||||
|
||||
var unsupportedRules = [];
|
||||
var ruleMap = {
|
||||
'SpaceAfterSemicolonInFor': 'InsertSpaceAfterSemicolonInForStatements',
|
||||
'SpaceAfterComma': 'InsertSpaceAfterCommaDelimiter',
|
||||
'NewLineBeforeOpenCurlyInControl': 'PlaceOpenBraceOnNewLineForControlBlocks',
|
||||
'NewLineBeforeOpenCurlyInFunction': 'PlaceOpenBraceOnNewLineForFunctions'
|
||||
};
|
||||
|
||||
var options = new Services.FormatCodeOptions();
|
||||
if (test.rules.indexOf('SpaceBeforeBinaryOperator') >= 0 && test.rules.indexOf('SpaceAfterBinaryOperator') >= 0) {
|
||||
test.rules.splice(test.rules.indexOf('SpaceBeforeBinaryOperator'), 1);
|
||||
test.rules.splice(test.rules.indexOf('SpaceAfterBinaryOperator'), 1);
|
||||
options.InsertSpaceBeforeAndAfterBinaryOperators = true;
|
||||
}
|
||||
|
||||
test.rules.forEach(ruleName => {
|
||||
if (options[ruleName] !== undefined) {
|
||||
// The options struct has a matching property, just set it directly
|
||||
options[ruleName] = true;
|
||||
} else {
|
||||
if (ruleMap[ruleName] !== undefined) {
|
||||
// We have a remapping of this name, use that instead
|
||||
options[ruleMap[ruleName]] = true;
|
||||
} else {
|
||||
if (ruleName.indexOf('No') === 0) {
|
||||
// This is a 'NoFoo', set 'Foo' to false
|
||||
options[ruleMap[ruleName.substr(2)]] = false;
|
||||
} else {
|
||||
// ??
|
||||
IO.printLine('Unsupported rule name ' + ruleName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var edits = ls.getFormattingEditsForRange(filename, test.span.start, test.span.start + test.span.length, options);
|
||||
|
||||
var output = typescriptLS.applyEdits(test.input, edits);
|
||||
|
||||
// Normalize line endings
|
||||
output = output.replace(/\r\n/g, '\n');
|
||||
test.expected = test.expected.replace(/\r\n/g, '\n');
|
||||
|
||||
if (output != test.expected) {
|
||||
var outputHtml = '';
|
||||
outputHtml += '<table class="test-table">';
|
||||
outputHtml += '<tr class="test-header-row">';
|
||||
outputHtml += '<th>Input</th><th>Output</th><th>Expected</th>';
|
||||
outputHtml += '</tr>';
|
||||
outputHtml += '<tr class="test-results-row">';
|
||||
outputHtml += '<td class="test-input code">' + markupCodeForHtml(test.input) + '</td>';
|
||||
outputHtml += '<td class="test-output code">' + markupCodeForHtml(output) + '</td>';
|
||||
outputHtml += '<td class="test-expected code">' + markupCodeForHtml(test.expected) + '</td>';
|
||||
outputHtml += '</tr>';
|
||||
outputHtml += '<tr class="test-operations-row">';
|
||||
outputHtml += '<td colspan="3">Format from character ' + test.span.start + ' to ' + (test.span.start + test.span.length) + ' with rules: ' + test.rules.join(', ') + '</td>';
|
||||
outputHtml += '</tr>';
|
||||
outputHtml += '</table>'; // test-table
|
||||
|
||||
IO.writeFile(outputFile, IO.readFile(outputFile).contents() + outputHtml, false);
|
||||
|
||||
// TODO: Uncomment when things are working
|
||||
// throw new Error("Formatting failed - refer to diff-1.html");
|
||||
}
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
for (var i = 0; i < documentTests.length; i++) {
|
||||
var test = documentTests[i];
|
||||
|
||||
var msg = 'formats the code (index ' + i + ') from ' + test.span.start + ' to ' + (test.span.start + test.span.length) + ' with rules = [' + test.rules.join(', ') + '] correctly';
|
||||
it(msg, function(t) {
|
||||
return function() {
|
||||
checkTest(t);
|
||||
}
|
||||
}(test));
|
||||
}
|
||||
});
|
||||
|
||||
describe('importedJavaScriptFormatting - formatting operations', function() {
|
||||
var outputFile = 'diff-2.html';
|
||||
IO.writeFile(outputFile, IO.readFile(Harness.userSpecifiedroot + 'tests/cases/unittests/services/formatDiffTemplate.html').contents(), false);
|
||||
|
||||
var checkTest = function(test: FormatOperationTestJson) {
|
||||
var filename = 'temp.ts';
|
||||
var typescriptLS = new Harness.TypeScriptLS();
|
||||
typescriptLS.addScript(filename, test.input);
|
||||
|
||||
var ls = typescriptLS.getLanguageService();
|
||||
|
||||
var operationsText = '';
|
||||
|
||||
var markedUpInput = test.input;
|
||||
var output = test.input;
|
||||
|
||||
for (var i = 0; i < test.operations.length; i++) {
|
||||
var options = new Services.FormatCodeOptions();
|
||||
var op = test.operations[i];
|
||||
var edits: Services.TextEdit[];
|
||||
|
||||
if (op.operation === 'CloseBrace') {
|
||||
edits = ls.languageService.getFormattingEditsAfterKeystroke(filename, op.point.position, '}', options);
|
||||
operationsText += 'Format for } at position ' + op.point.position.toString();
|
||||
markedUpInput = markedUpInput.substring(0, op.point.position) + '✪' + markedUpInput.substring(op.point.position);
|
||||
} else if (op.operation === 'Enter') {
|
||||
edits = ls.languageService.getFormattingEditsAfterKeystroke(filename, op.point.position, '\n', options);
|
||||
operationsText += 'Format for [enter] at position ' + op.point.position.toString();
|
||||
markedUpInput = markedUpInput.substring(0, op.point.position) + '✪' + markedUpInput.substring(op.point.position);
|
||||
} else if (op.operation === 'Semicolon') {
|
||||
edits = ls.languageService.getFormattingEditsAfterKeystroke(filename, op.point.position, ';', options);
|
||||
operationsText += 'Format for ; at position ' + op.point.position.toString();
|
||||
markedUpInput = markedUpInput.substring(0, op.point.position) + '✪' + markedUpInput.substring(op.point.position);
|
||||
} else if (op.operation === 'Document') {
|
||||
edits = ls.languageService.getFormattingEditsForRange(filename, 0, output.length, options);
|
||||
operationsText += 'Format Document';
|
||||
} else if (op.operation === 'Selection') {
|
||||
edits = ls.languageService.getFormattingEditsForRange(filename, op.span.start, op.span.start + op.span.length, options);
|
||||
operationsText += 'Format selection from ' + op.span.start + ', length = ' + op.span.length;
|
||||
} else if (op.operation === 'Paste') {
|
||||
edits = ls.languageService.getFormattingEditsForRange(filename, op.span.start, op.span.start + op.span.length, options);
|
||||
operationsText += 'Format pasted content from ' + op.span.start + ', length = ' + op.span.length;
|
||||
} else {
|
||||
throw new Error('Unknown operation: ' + op.operation);
|
||||
}
|
||||
|
||||
output = typescriptLS.applyEdits(test.input, edits);
|
||||
typescriptLS.updateScript(filename, output);
|
||||
}
|
||||
|
||||
// Normalize line endings
|
||||
output = output.replace(/\r\n/g, '\n');
|
||||
test.expected = test.expected.replace(/\r\n/g, '\n');
|
||||
|
||||
var outputHtml = '';
|
||||
outputHtml += '<table class="test-table">';
|
||||
outputHtml += '<tr class="test-header-row">';
|
||||
outputHtml += '<th>Input</th><th>Output</th><th>Expected</th>';
|
||||
outputHtml += '</tr>';
|
||||
outputHtml += '<tr class="test-results-row">';
|
||||
outputHtml += '<td class="test-input code">' + markupCodeForHtml(markedUpInput) + '</td>';
|
||||
outputHtml += '<td class="test-output code">' + markupCodeForHtml(output) + '</td>';
|
||||
outputHtml += '<td class="test-expected code">' + markupCodeForHtml(test.expected) + '</td>';
|
||||
outputHtml += '</tr>';
|
||||
outputHtml += '<tr class="test-operations-row">';
|
||||
outputHtml += '<td colspan="3">' + operationsText + '</td>';
|
||||
outputHtml += '</tr>';
|
||||
outputHtml += '</table>'; // test-table
|
||||
|
||||
if (test.expected == output) {
|
||||
// Pass
|
||||
} else {
|
||||
IO.writeFile(outputFile, IO.readFile(outputFile).contents() + outputHtml, false);
|
||||
// TODO: Uncomment when things are working
|
||||
// throw new Error('Format test failed - refer to ' + outputFile);
|
||||
}
|
||||
}
|
||||
|
||||
var operationsTests: FormatOperationTestJson[] = eval('[' + IO.readFile(Harness.userSpecifiedroot + 'tests/cases/unittests/services/ruleFormattingTests.json').contents() + ']');
|
||||
for (var i = 0; i < operationsTests.length; i++) {
|
||||
var test = operationsTests[i];
|
||||
|
||||
var msg = 'formats the text correctly, line = ' + i;
|
||||
it(msg, function(t) {
|
||||
return function() {
|
||||
checkTest(t);
|
||||
}
|
||||
}(test));
|
||||
}
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user