9
9
// the APACHE 2.0 license. Some utility functions and
10
10
// TypeScript were also lifted.
11
11
12
+ import * as path from 'path' ;
13
+ import * as fs from 'fs' ;
12
14
import * as ts from 'typescript' ;
13
15
import * as ng from '@angular/language-service' ;
14
16
@@ -799,21 +801,22 @@ export class Project {
799
801
800
802
constructor (
801
803
public projectService : ProjectService ,
804
+ private logger : Logger ,
802
805
public projectOptions ?: ProjectOptions ,
803
806
public languageServiceDiabled = false ) {
804
807
if ( projectOptions && projectOptions . files ) {
805
808
// If files are listed explicitly, allow all extensions
806
809
projectOptions . compilerOptions [ 'allowNonTsExtensions' ] = true ;
807
810
}
808
811
if ( ! languageServiceDiabled ) {
809
- this . compilerService = new CompilerService ( this , projectOptions && projectOptions . compilerOptions ) ;
812
+ this . compilerService = new CompilerService ( this , logger , projectOptions && projectOptions . compilerOptions ) ;
810
813
}
811
814
}
812
815
813
816
enableLanguageService ( ) {
814
817
// if the language service was disabled, we should re-initiate the compiler service
815
818
if ( this . languageServiceDiabled ) {
816
- this . compilerService = new CompilerService ( this , this . projectOptions && this . projectOptions . compilerOptions ) ;
819
+ this . compilerService = new CompilerService ( this , this . logger , this . projectOptions && this . projectOptions . compilerOptions ) ;
817
820
}
818
821
this . languageServiceDiabled = false ;
819
822
}
@@ -1072,16 +1075,6 @@ export class ProjectService {
1072
1075
} ;
1073
1076
}
1074
1077
1075
- // getFormatCodeOptions(file?: string) {
1076
- // if (file) {
1077
- // const info = this.filenameToScriptInfo[file];
1078
- // if (info) {
1079
- // return info.formatCodeOptions;
1080
- // }
1081
- // }
1082
- // return this.hostConfiguration.formatCodeOptions;
1083
- // }
1084
-
1085
1078
watchedFileChanged ( fileName : string ) {
1086
1079
const info = this . filenameToScriptInfo [ fileName ] ;
1087
1080
if ( ! info ) {
@@ -1210,32 +1203,12 @@ export class ProjectService {
1210
1203
this . psLogger . msg ( msg , type ) ;
1211
1204
}
1212
1205
1213
- // setHostConfiguration(args: ts.server.protocol.ConfigureRequestArguments) {
1214
- // if (args.file) {
1215
- // const info = this.filenameToScriptInfo[args.file];
1216
- // if (info) {
1217
- // info.setFormatOptions(args.formatOptions);
1218
- // this.log("Host configuration update for file " + args.file, "Info");
1219
- // }
1220
- // }
1221
- // else {
1222
- // if (args.hostInfo !== undefined) {
1223
- // this.hostConfiguration.hostInfo = args.hostInfo;
1224
- // this.log("Host information " + args.hostInfo, "Info");
1225
- // }
1226
- // if (args.formatOptions) {
1227
- // mergeFormatOptions(this.hostConfiguration.formatCodeOptions, args.formatOptions);
1228
- // this.log("Format host information updated", "Info");
1229
- // }
1230
- // }
1231
- // }
1232
-
1233
1206
closeLog ( ) {
1234
1207
this . psLogger . close ( ) ;
1235
1208
}
1236
1209
1237
1210
createInferredProject ( root : ScriptInfo ) {
1238
- const project = new Project ( this ) ;
1211
+ const project = new Project ( this , this . psLogger ) ;
1239
1212
project . addRoot ( root ) ;
1240
1213
1241
1214
let currentPath = getDirectoryPath ( root . fileName ) ;
@@ -1867,53 +1840,20 @@ export class ProjectService {
1867
1840
}
1868
1841
}
1869
1842
1870
- // private exceedTotalNonTsFileSizeLimit(fileNames: string[]) {
1871
- // let totalNonTsFileSize = 0;
1872
- // if (!this.host.getFileSize) {
1873
- // return false;
1874
- // }
1875
-
1876
- // for (const fileName of fileNames) {
1877
- // if (hasTypeScriptFileExtension(fileName)) {
1878
- // continue;
1879
- // }
1880
- // totalNonTsFileSize += this.host.getFileSize(fileName);
1881
- // if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) {
1882
- // return true;
1883
- // }
1884
- // }
1885
- // return false;
1886
- // }
1887
-
1888
1843
openConfigFile ( configFilename : string , clientFileName ?: string ) : { project ?: Project , errors : ts . Diagnostic [ ] } {
1889
1844
const parseConfigFileResult = this . configFileToProjectOptions ( configFilename ) ;
1890
1845
let errors = parseConfigFileResult . errors ;
1891
1846
if ( ! parseConfigFileResult . projectOptions ) {
1892
1847
return { errors } ;
1893
1848
}
1894
1849
const projectOptions = parseConfigFileResult . projectOptions ;
1895
- // if (!projectOptions.compilerOptions.disableSizeLimit && projectOptions.compilerOptions.allowJs) {
1896
- // if (this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
1897
- // const project = this.createProject(configFilename, projectOptions, /*languageServiceDisabled*/ true);
1898
-
1899
- // // for configured projects with languageService disabled, we only watch its config file,
1900
- // // do not care about the directory changes in the folder.
1901
- // project.projectFileWatcher = this.host.watchFile(
1902
- // toPath(configFilename, configFilename, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)),
1903
- // _ => this.watchedProjectConfigFileChanged(project));
1904
- // return { project, errors };
1905
- // }
1906
- // }
1907
1850
1908
1851
const project = this . createProject ( configFilename , projectOptions ) ;
1909
1852
for ( const rootFilename of projectOptions . files ) {
1910
1853
if ( this . host . fileExists ( rootFilename ) ) {
1911
1854
const info = this . openFile ( rootFilename , /*openedByClient*/ clientFileName == rootFilename ) ;
1912
1855
project . addRoot ( info ) ;
1913
1856
}
1914
- else {
1915
- // (errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.File_0_not_found, rootFilename));
1916
- }
1917
1857
}
1918
1858
project . finishGraph ( ) ;
1919
1859
project . projectFileWatcher = this . host . watchFile ( configFilename , _ => this . watchedProjectConfigFileChanged ( project ) ) ;
@@ -1955,19 +1895,6 @@ export class ProjectService {
1955
1895
return errors ;
1956
1896
}
1957
1897
else {
1958
- // if (projectOptions.compilerOptions && !projectOptions.compilerOptions.disableSizeLimit && this.exceedTotalNonTsFileSizeLimit(projectOptions.files)) {
1959
- // project.setProjectOptions(projectOptions);
1960
- // if (project.languageServiceDiabled) {
1961
- // return errors;
1962
- // }
1963
-
1964
- // project.disableLanguageService();
1965
- // if (project.directoryWatcher) {
1966
- // project.directoryWatcher.close();
1967
- // project.directoryWatcher = undefined;
1968
- // }
1969
- // return errors;
1970
- // }
1971
1898
1972
1899
if ( project . languageServiceDiabled ) {
1973
1900
project . setProjectOptions ( projectOptions ) ;
@@ -2036,7 +1963,7 @@ export class ProjectService {
2036
1963
}
2037
1964
2038
1965
createProject ( projectFilename : string , projectOptions ?: ProjectOptions , languageServiceDisabled ?: boolean ) {
2039
- const project = new Project ( this , projectOptions , languageServiceDisabled ) ;
1966
+ const project = new Project ( this , this . psLogger , projectOptions , languageServiceDisabled ) ;
2040
1967
project . projectFilename = projectFilename ;
2041
1968
return project ;
2042
1969
}
@@ -2051,8 +1978,9 @@ export class CompilerService {
2051
1978
classifier : ts . Classifier ;
2052
1979
settings : ts . CompilerOptions ;
2053
1980
documentRegistry = ts . createDocumentRegistry ( ) ;
1981
+ ng : typeof ng ;
2054
1982
2055
- constructor ( public project : Project , opt ?: ts . CompilerOptions ) {
1983
+ constructor ( public project : Project , private logger : Logger , opt ?: ts . CompilerOptions ) {
2056
1984
this . host = new LSHost ( project . projectService . host , project ) ;
2057
1985
if ( opt ) {
2058
1986
this . setCompilerOptions ( opt ) ;
@@ -2063,9 +1991,13 @@ export class CompilerService {
2063
1991
defaultOpts . allowJs = true ;
2064
1992
this . setCompilerOptions ( defaultOpts ) ;
2065
1993
}
1994
+
1995
+
2066
1996
this . languageService = ts . createLanguageService ( this . host , this . documentRegistry ) ;
2067
- this . ngHost = new ng . TypeScriptServiceHost ( ts , this . host , this . languageService ) ;
2068
- this . ngService = ng . createLanguageService ( this . ngHost ) ;
1997
+
1998
+ this . ng = this . resolveLanguageServiceModule ( ) ;
1999
+ this . ngHost = new this . ng . TypeScriptServiceHost ( ts , this . host , this . languageService ) ;
2000
+ this . ngService = this . ng . createLanguageService ( this . ngHost ) ;
2069
2001
this . ngHost . setSite ( this . ngService ) ;
2070
2002
this . classifier = ts . createClassifier ( ) ;
2071
2003
}
@@ -2080,6 +2012,29 @@ export class CompilerService {
2080
2012
return ts . isExternalModule ( sourceFile ) ;
2081
2013
}
2082
2014
2015
+ resolveLanguageServiceModule ( ) : typeof ng {
2016
+ const host = path . resolve ( this . host . getCurrentDirectory ( ) , 'main.ts' ) ;
2017
+ const modules = this . host . resolveModuleNames ( [ '@angular/language-service' ] , host ) ;
2018
+ if ( modules && modules [ 0 ] ) {
2019
+ const resolvedModule = modules [ 0 ] ;
2020
+ const moduleName = path . dirname ( resolvedModule . resolvedFileName ) ;
2021
+ if ( fs . existsSync ( moduleName ) ) {
2022
+ try {
2023
+ const result : typeof ng = require ( moduleName ) ;
2024
+ if ( result ) return result ;
2025
+ } catch ( e ) {
2026
+ this . log ( `Error loading module "${ moduleName } "; using local language service instead` ) ;
2027
+ this . log ( e . stack ) ;
2028
+ }
2029
+ }
2030
+ }
2031
+ return ng ;
2032
+ }
2033
+
2034
+ private log ( message : string ) {
2035
+ return this . logger . msg ( message ) ;
2036
+ }
2037
+
2083
2038
static getDefaultFormatCodeOptions ( host : ProjectServiceHost ) : ts . FormatCodeOptions {
2084
2039
return clone ( {
2085
2040
BaseIndentSize : 0 ,
0 commit comments