1
1
import { EOL } from "os" ;
2
2
import * as path from "path" ;
3
3
import * as helpers from "../common/helpers" ;
4
- import { TrackActionNames } from "../constants" ;
4
+ import { TrackActionNames , NODE_MODULES_FOLDER_NAME , TNS_CORE_MODULES_NAME } from "../constants" ;
5
5
import { doctor , constants } from "nativescript-doctor" ;
6
6
7
- class DoctorService implements IDoctorService {
7
+ export class DoctorService implements IDoctorService {
8
8
private static DarwinSetupScriptLocation = path . join ( __dirname , ".." , ".." , "setup" , "mac-startup-shell-script.sh" ) ;
9
9
private static WindowsSetupScriptExecutable = "powershell.exe" ;
10
10
private static WindowsSetupScriptArguments = [ "start-process" , "-FilePath" , "PowerShell.exe" , "-NoNewWindow" , "-Wait" , "-ArgumentList" , '"-NoProfile -ExecutionPolicy Bypass -Command iex ((new-object net.webclient).DownloadString(\'https://www.nativescript.org/setup/win\'))"' ] ;
@@ -14,10 +14,12 @@ class DoctorService implements IDoctorService {
14
14
private $logger : ILogger ,
15
15
private $childProcess : IChildProcess ,
16
16
private $injector : IInjector ,
17
+ private $projectDataService : IProjectDataService ,
18
+ private $fs : IFileSystem ,
17
19
private $terminalSpinnerService : ITerminalSpinnerService ,
18
20
private $versionsService : IVersionsService ) { }
19
21
20
- public async printWarnings ( configOptions ?: { trackResult : boolean , projectDir ?: string , runtimeVersion ?: string , options ?: IOptions } ) : Promise < void > {
22
+ public async printWarnings ( configOptions ?: { trackResult : boolean , projectDir ?: string , runtimeVersion ?: string , options ?: IOptions } ) : Promise < void > {
21
23
const infos = await this . $terminalSpinnerService . execute < NativeScriptDoctor . IInfo [ ] > ( {
22
24
text : `Getting environment information ${ EOL } `
23
25
} , ( ) => doctor . getInfos ( { projectDir : configOptions && configOptions . projectDir , androidRuntimeVersion : configOptions && configOptions . runtimeVersion } ) ) ;
@@ -48,6 +50,14 @@ class DoctorService implements IDoctorService {
48
50
this . $logger . error ( "Cannot get the latest versions information from npm. Please try again later." ) ;
49
51
}
50
52
53
+ try {
54
+ if ( configOptions . projectDir ) {
55
+ this . checkForDeprecatedShortImportsInAppDir ( configOptions . projectDir ) ;
56
+ }
57
+ } catch ( err ) {
58
+ this . $logger . trace ( `Unable to validate if project has short imports. Error is` , err ) ;
59
+ }
60
+
51
61
await this . $injector . resolve < IPlatformEnvironmentRequirements > ( "platformEnvironmentRequirements" ) . checkEnvironmentRequirements ( {
52
62
platform : null ,
53
63
projectDir : configOptions && configOptions . projectDir ,
@@ -113,6 +123,53 @@ class DoctorService implements IDoctorService {
113
123
return ! hasWarnings ;
114
124
}
115
125
126
+ public checkForDeprecatedShortImportsInAppDir ( projectDir : string ) : void {
127
+ const files = this . $projectDataService . getAppExecutableFiles ( projectDir ) ;
128
+ const shortImports = this . getDeprecatedShortImportsInFiles ( files , projectDir ) ;
129
+ if ( shortImports . length ) {
130
+ this . $logger . printMarkdown ( "Detected short imports in your application. Please note that `short imports are deprecated` since NativeScript 5.2.0. More information can be found in this blogpost https://www.nativescript.org/blog/say-goodbye-to-short-imports-in-nativescript" ) ;
131
+ shortImports . forEach ( shortImport => {
132
+ this . $logger . printMarkdown ( `In file \`${ shortImport . file } \` line \`${ shortImport . line } \` is short import. Add \`tns-core-modules/\` in front of the required/imported module.` ) ;
133
+ } ) ;
134
+ }
135
+ }
136
+
137
+ protected getDeprecatedShortImportsInFiles ( files : string [ ] , projectDir : string ) : { file : string , line : string } [ ] {
138
+ const shortImportRegExps = this . getShortImportRegExps ( projectDir ) ;
139
+ const shortImports : { file : string , line : string } [ ] = [ ] ;
140
+
141
+ for ( const file of files ) {
142
+ const fileContent = this . $fs . readText ( file ) ;
143
+ const strippedComments = helpers . stripComments ( fileContent ) ;
144
+ const linesWithRequireStatements = strippedComments
145
+ . split ( / \r ? \n / )
146
+ . filter ( line => / \b t n s - c o r e - m o d u l e s \b / . exec ( line ) === null && ( / \b i m p o r t \b / . exec ( line ) || / \b r e q u i r e \b / . exec ( line ) ) ) ;
147
+
148
+ for ( const line of linesWithRequireStatements ) {
149
+ for ( const regExp of shortImportRegExps ) {
150
+ const matches = line . match ( regExp ) ;
151
+
152
+ if ( matches && matches . length ) {
153
+ shortImports . push ( { file, line } ) ;
154
+ break ;
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ return shortImports ;
161
+ }
162
+
163
+ private getShortImportRegExps ( projectDir : string ) : RegExp [ ] {
164
+ const pathToTnsCoreModules = path . join ( projectDir , NODE_MODULES_FOLDER_NAME , TNS_CORE_MODULES_NAME ) ;
165
+ const contents = this . $fs . readDirectory ( pathToTnsCoreModules )
166
+ . filter ( entry => this . $fs . getFsStats ( path . join ( pathToTnsCoreModules , entry ) ) . isDirectory ( ) ) ;
167
+
168
+ const regExps = contents . map ( c => new RegExp ( `[\"\']${ c } [\"\'/]` , "g" ) ) ;
169
+
170
+ return regExps ;
171
+ }
172
+
116
173
private async runSetupScriptCore ( executablePath : string , setupScriptArgs : string [ ] ) : Promise < ISpawnResult > {
117
174
return this . $childProcess . spawnFromEvent ( executablePath , setupScriptArgs , "close" , { stdio : "inherit" } ) ;
118
175
}
0 commit comments