2020-03-31 20:42:07 +08:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
var bs _logger _1 = require ( "bs-logger" ) ;
var memoize = require ( "lodash.memoize" ) ;
var path _1 = require ( "path" ) ;
2020-04-30 20:40:07 +08:00
var constants _1 = require ( "../constants" ) ;
2020-03-31 20:42:07 +08:00
var messages _1 = require ( "../util/messages" ) ;
2020-04-30 20:40:07 +08:00
var compiler _utils _1 = require ( "./compiler-utils" ) ;
function doTypeChecking ( configs , fileName , service , logger ) {
if ( configs . shouldReportDiagnostic ( fileName ) ) {
var diagnostics = service . getSemanticDiagnostics ( fileName ) . concat ( service . getSyntacticDiagnostics ( fileName ) ) ;
configs . raiseDiagnostics ( diagnostics , fileName , logger ) ;
}
}
2020-03-31 20:42:07 +08:00
exports . compileUsingLanguageService = function ( configs , logger , memoryCache ) {
var _a ;
logger . debug ( 'compileUsingLanguageService(): create typescript compiler' ) ;
2020-04-30 20:40:07 +08:00
var ts = configs . compilerModule ;
var cwd = configs . cwd ;
var cacheDir = configs . tsCacheDir ;
var options = configs . typescript . options ;
var serviceHostTraceCtx = ( _a = {
2020-03-31 20:42:07 +08:00
namespace : 'ts:serviceHost' ,
call : null
} ,
_a [ bs _logger _1 . LogContexts . logLevel ] = bs _logger _1 . LogLevels . trace ,
_a ) ;
var projectVersion = 1 ;
2020-04-30 20:40:07 +08:00
var updateMemoryCache = function ( contents , fileName ) {
2020-03-31 20:42:07 +08:00
var _a ;
logger . debug ( { fileName : fileName } , "updateMemoryCache(): update memory cache for language service" ) ;
2020-04-30 20:40:07 +08:00
var shouldIncrementProjectVersion = false ;
var fileVersion = ( _a = memoryCache . versions [ fileName ] ) !== null && _a !== void 0 ? _a : 0 ;
var isFileInCache = fileVersion !== 0 ;
2020-03-31 20:42:07 +08:00
if ( ! isFileInCache ) {
memoryCache . versions [ fileName ] = 1 ;
2020-04-30 20:40:07 +08:00
shouldIncrementProjectVersion = true ;
2020-03-31 20:42:07 +08:00
}
2020-04-30 20:40:07 +08:00
var previousContents = memoryCache . contents [ fileName ] ;
if ( previousContents !== contents ) {
2020-03-31 20:42:07 +08:00
memoryCache . versions [ fileName ] = fileVersion + 1 ;
2020-04-30 20:40:07 +08:00
memoryCache . contents [ fileName ] = contents ;
if ( isFileInCache )
shouldIncrementProjectVersion = true ;
2020-03-31 20:42:07 +08:00
}
2020-04-30 20:40:07 +08:00
if ( shouldIncrementProjectVersion )
projectVersion ++ ;
2020-03-31 20:42:07 +08:00
} ;
var serviceHost = {
getProjectVersion : function ( ) { return String ( projectVersion ) ; } ,
getScriptFileNames : function ( ) { return Object . keys ( memoryCache . versions ) ; } ,
getScriptVersion : function ( fileName ) {
2020-04-30 20:40:07 +08:00
var normalizedFileName = path _1 . normalize ( fileName ) ;
var version = memoryCache . versions [ normalizedFileName ] ;
2020-03-31 20:42:07 +08:00
return version === undefined ? undefined : String ( version ) ;
} ,
getScriptSnapshot : function ( fileName ) {
2020-04-30 20:40:07 +08:00
var normalizedFileName = path _1 . normalize ( fileName ) ;
var hit = compiler _utils _1 . hasOwn . call ( memoryCache . contents , normalizedFileName ) ;
2020-03-31 20:42:07 +08:00
logger . trace ( { normalizedFileName : normalizedFileName , cacheHit : hit } , "getScriptSnapshot():" , 'cache' , hit ? 'hit' : 'miss' ) ;
2020-04-30 20:40:07 +08:00
if ( ! hit )
2020-03-31 20:42:07 +08:00
memoryCache . contents [ normalizedFileName ] = ts . sys . readFile ( normalizedFileName ) ;
var contents = memoryCache . contents [ normalizedFileName ] ;
2020-04-30 20:40:07 +08:00
if ( contents === undefined )
2020-03-31 20:42:07 +08:00
return ;
return ts . ScriptSnapshot . fromString ( contents ) ;
} ,
fileExists : memoize ( ts . sys . fileExists ) ,
readFile : logger . wrap ( serviceHostTraceCtx , 'readFile' , memoize ( ts . sys . readFile ) ) ,
readDirectory : memoize ( ts . sys . readDirectory ) ,
getDirectories : memoize ( ts . sys . getDirectories ) ,
directoryExists : memoize ( ts . sys . directoryExists ) ,
realpath : memoize ( ts . sys . realpath ) ,
2020-04-30 20:40:07 +08:00
getNewLine : function ( ) { return constants _1 . LINE _FEED ; } ,
2020-03-31 20:42:07 +08:00
getCurrentDirectory : function ( ) { return cwd ; } ,
getCompilationSettings : function ( ) { return options ; } ,
getDefaultLibFileName : function ( ) { return ts . getDefaultLibFilePath ( options ) ; } ,
getCustomTransformers : function ( ) { return configs . tsCustomTransformers ; } ,
} ;
logger . debug ( 'compileUsingLanguageService(): creating language service' ) ;
var service = ts . createLanguageService ( serviceHost ) ;
return {
compileFn : function ( code , fileName ) {
var normalizedFileName = path _1 . normalize ( fileName ) ;
logger . debug ( { normalizedFileName : normalizedFileName } , 'compileFn(): compiling using language service' ) ;
updateMemoryCache ( code , normalizedFileName ) ;
var output = service . getEmitOutput ( normalizedFileName ) ;
2020-04-30 20:40:07 +08:00
logger . debug ( "diagnoseFn(): computing diagnostics for " + normalizedFileName + " using language service" ) ;
doTypeChecking ( configs , normalizedFileName , service , logger ) ;
if ( cacheDir ) {
if ( compiler _utils _1 . isTestFile ( configs . testMatchPatterns , normalizedFileName ) ) {
compiler _utils _1 . cacheResolvedModules ( normalizedFileName , code , memoryCache , service . getProgram ( ) , cacheDir , logger ) ;
}
else {
Object . entries ( memoryCache . resolvedModules )
. filter ( function ( entry ) {
return ( entry [ 1 ] . modulePaths . find ( function ( modulePath ) { return modulePath === normalizedFileName ; } ) &&
! compiler _utils _1 . hasOwn . call ( memoryCache . outputs , entry [ 0 ] ) ) ;
} )
. forEach ( function ( entry ) {
logger . debug ( "diagnoseFn(): computing diagnostics for test file that imports " + normalizedFileName + " using language service" ) ;
var testFileName = entry [ 0 ] ;
updateMemoryCache ( entry [ 1 ] . testFileContent , testFileName ) ;
doTypeChecking ( configs , testFileName , service , logger ) ;
} ) ;
}
}
2020-03-31 20:42:07 +08:00
if ( output . emitSkipped ) {
throw new TypeError ( path _1 . relative ( cwd , normalizedFileName ) + ": Emit skipped for language service" ) ;
}
if ( ! output . outputFiles . length ) {
throw new TypeError ( messages _1 . interpolate ( "Unable to require `.d.ts` file for file: {{file}}.\nThis is usually the result of a faulty configuration or import. Make sure there is a `.js`, `.json` or another executable extension available alongside `{{file}}`." , {
file : path _1 . basename ( normalizedFileName ) ,
} ) ) ;
}
return [ output . outputFiles [ 1 ] . text , output . outputFiles [ 0 ] . text ] ;
} ,
program : service . getProgram ( ) ,
} ;
} ;