@@ -25,6 +25,7 @@ import {
25
25
normalizePath ,
26
26
optionDeclarations ,
27
27
parseCustomTypeOption ,
28
+ ScriptTarget ,
28
29
toPath ,
29
30
transpileOptionValueCompilerOptions ,
30
31
} from "./_namespaces/ts" ;
@@ -51,14 +52,64 @@ const optionsRedundantWithVerbatimModuleSyntax = new Set([
51
52
52
53
/*
53
54
* This function will compile source text from 'input' argument using specified compiler options.
54
- * If not options are provided - it will use a set of default compiler options.
55
+ * If no options are provided - it will use a set of default compiler options.
55
56
* Extra compiler options that will unconditionally be used by this function are:
56
57
* - isolatedModules = true
57
58
* - allowNonTsExtensions = true
58
59
* - noLib = true
59
60
* - noResolve = true
61
+ * - declaration = false
60
62
*/
61
63
export function transpileModule ( input : string , transpileOptions : TranspileOptions ) : TranspileOutput {
64
+ return transpileWorker ( input , transpileOptions , /*declaration*/ false ) ;
65
+ }
66
+
67
+ /*
68
+ * This function will create a declaration file from 'input' argument using specified compiler options.
69
+ * If no options are provided - it will use a set of default compiler options.
70
+ * Extra compiler options that will unconditionally be used by this function are:
71
+ * - isolatedDeclarations = true
72
+ * - isolatedModules = true
73
+ * - allowNonTsExtensions = true
74
+ * - noLib = true
75
+ * - noResolve = true
76
+ * - declaration = true
77
+ * - emitDeclarationOnly = true
78
+ * Note that this declaration file may differ from one produced by a full program typecheck,
79
+ * in that only types in the single input file are available to be used in the generated declarations.
80
+ */
81
+ export function transpileDeclaration ( input : string , transpileOptions : TranspileOptions ) : TranspileOutput {
82
+ return transpileWorker ( input , transpileOptions , /*declaration*/ true ) ;
83
+ }
84
+
85
+ // Declaration emit works without a `lib`, but some local inferences you'd expect to work won't without
86
+ // at least a minimal `lib` available, since the checker will `any` their types without these defined.
87
+ // Late bound symbol names, in particular, are impossible to define without `Symbol` at least partially defined.
88
+ // TODO: This should *probably* just load the full, real `lib` for the `target`.
89
+ const barebonesLibContent = `/// <reference no-default-lib="true"/>
90
+ interface Boolean {}
91
+ interface Function {}
92
+ interface CallableFunction {}
93
+ interface NewableFunction {}
94
+ interface IArguments {}
95
+ interface Number {}
96
+ interface Object {}
97
+ interface RegExp {}
98
+ interface String {}
99
+ interface Array<T> { length: number; [n: number]: T; }
100
+ interface SymbolConstructor {
101
+ (desc?: string | number): symbol;
102
+ for(name: string): symbol;
103
+ readonly toStringTag: symbol;
104
+ }
105
+ declare var Symbol: SymbolConstructor;
106
+ interface Symbol {
107
+ readonly [Symbol.toStringTag]: string;
108
+ }` ;
109
+ const barebonesLibName = "lib.d.ts" ;
110
+ const barebonesLibSourceFile = createSourceFile ( barebonesLibName , barebonesLibContent , { languageVersion : ScriptTarget . Latest } ) ;
111
+
112
+ function transpileWorker ( input : string , transpileOptions : TranspileOptions , declaration ?: boolean ) : TranspileOutput {
62
113
const diagnostics : Diagnostic [ ] = [ ] ;
63
114
64
115
const options : CompilerOptions = transpileOptions . compilerOptions ? fixupCompilerOptions ( transpileOptions . compilerOptions , diagnostics ) : { } ;
@@ -86,10 +137,19 @@ export function transpileModule(input: string, transpileOptions: TranspileOption
86
137
// Filename can be non-ts file.
87
138
options . allowNonTsExtensions = true ;
88
139
140
+ if ( declaration ) {
141
+ options . declaration = true ;
142
+ options . emitDeclarationOnly = true ;
143
+ options . isolatedDeclarations = true ;
144
+ }
145
+ else {
146
+ options . declaration = false ;
147
+ }
148
+
89
149
const newLine = getNewLineCharacter ( options ) ;
90
150
// Create a compilerHost object to allow the compiler to read and write files
91
151
const compilerHost : CompilerHost = {
92
- getSourceFile : fileName => fileName === normalizePath ( inputFileName ) ? sourceFile : undefined ,
152
+ getSourceFile : fileName => fileName === normalizePath ( inputFileName ) ? sourceFile : fileName === normalizePath ( barebonesLibName ) ? barebonesLibSourceFile : undefined ,
93
153
writeFile : ( name , text ) => {
94
154
if ( fileExtensionIs ( name , ".map" ) ) {
95
155
Debug . assertEqual ( sourceMapText , undefined , "Unexpected multiple source map outputs, file:" , name ) ;
@@ -100,12 +160,12 @@ export function transpileModule(input: string, transpileOptions: TranspileOption
100
160
outputText = text ;
101
161
}
102
162
} ,
103
- getDefaultLibFileName : ( ) => "lib.d.ts" ,
163
+ getDefaultLibFileName : ( ) => barebonesLibName ,
104
164
useCaseSensitiveFileNames : ( ) => false ,
105
165
getCanonicalFileName : fileName => fileName ,
106
166
getCurrentDirectory : ( ) => "" ,
107
167
getNewLine : ( ) => newLine ,
108
- fileExists : ( fileName ) : boolean => fileName === inputFileName ,
168
+ fileExists : ( fileName ) : boolean => fileName === inputFileName || ( ! ! declaration && fileName === barebonesLibName ) ,
109
169
readFile : ( ) => "" ,
110
170
directoryExists : ( ) => true ,
111
171
getDirectories : ( ) => [ ] ,
@@ -135,14 +195,17 @@ export function transpileModule(input: string, transpileOptions: TranspileOption
135
195
let outputText : string | undefined ;
136
196
let sourceMapText : string | undefined ;
137
197
138
- const program = createProgram ( [ inputFileName ] , options , compilerHost ) ;
198
+ const inputs = declaration ? [ inputFileName , barebonesLibName ] : [ inputFileName ] ;
199
+ const program = createProgram ( inputs , options , compilerHost ) ;
139
200
140
201
if ( transpileOptions . reportDiagnostics ) {
141
202
addRange ( /*to*/ diagnostics , /*from*/ program . getSyntacticDiagnostics ( sourceFile ) ) ;
142
203
addRange ( /*to*/ diagnostics , /*from*/ program . getOptionsDiagnostics ( ) ) ;
143
204
}
144
205
// Emit
145
- program . emit ( /*targetSourceFile*/ undefined , /*writeFile*/ undefined , /*cancellationToken*/ undefined , /*emitOnlyDtsFiles*/ undefined , transpileOptions . transformers ) ;
206
+ const result = program . emit ( /*targetSourceFile*/ undefined , /*writeFile*/ undefined , /*cancellationToken*/ undefined , /*emitOnlyDtsFiles*/ declaration , transpileOptions . transformers , /*forceDtsEmit*/ declaration ) ;
207
+
208
+ addRange ( /*to*/ diagnostics , /*from*/ result . diagnostics ) ;
146
209
147
210
if ( outputText === undefined ) return Debug . fail ( "Output generation failed" ) ;
148
211
0 commit comments