11import { assert } from "chai" ;
2+ import { EventEmitter } from "events" ;
23import * as fs from "fs" ;
34import * as os from "os" ;
45import * as path from "path" ;
@@ -20,6 +21,9 @@ let xcodebuildCalls: string[][];
2021let writtenFiles : { [ path : string ] : string } ;
2122let warnings : string [ ] ;
2223let hookCalls : { name : string ; args : any } [ ] ;
24+ let errorsLogged : string [ ] ;
25+ let gradleOutput : { data : string ; pipe : string } [ ] | null ;
26+ let retraceOutput : string ;
2327
2428function createProjectData ( nsConfig : any = { } ) : any {
2529 return {
@@ -36,17 +40,18 @@ function createProjectData(nsConfig: any = {}): any {
3640
3741function createService ( nsConfig : any = { } ) : CompiledReleaseService {
3842 const injector : IInjector = new Yok ( ) ;
39- injector . register ( "childProcess" , {
43+ const childProcess = Object . assign ( new EventEmitter ( ) , {
4044 spawnFromEvent : async (
4145 command : string ,
4246 args : string [ ] ,
4347 _ : string ,
4448 options : any ,
4549 ) => {
4650 spawnCalls . push ( { command, args, options } ) ;
47- return { stdout : "" , stderr : "" , exitCode : 0 } ;
51+ return { stdout : retraceOutput , stderr : "" , exitCode : 0 } ;
4852 } ,
4953 } ) ;
54+ injector . register ( "childProcess" , childProcess ) ;
5055 injector . register ( "errors" , {
5156 fail : ( message : string ) => {
5257 throw new Error ( message ) ;
@@ -69,6 +74,12 @@ function createService(nsConfig: any = {}): CompiledReleaseService {
6974 injector . register ( "gradleCommandService" , {
7075 executeCommand : async ( args : string [ ] , options : IGradleCommandOptions ) => {
7176 gradleCalls . push ( { args, options } ) ;
77+ if ( gradleOutput ) {
78+ for ( const chunk of gradleOutput ) {
79+ childProcess . emit ( options . spawnOptions . emitOptions . eventName , chunk ) ;
80+ }
81+ throw new Error ( "Command gradlew failed with exit code 1" ) ;
82+ }
7283 } ,
7384 } ) ;
7485 injector . register ( "iOSProvisionService" , {
@@ -80,6 +91,8 @@ function createService(nsConfig: any = {}): CompiledReleaseService {
8091 injector . register ( "logger" , {
8192 info : ( ) : void => undefined ,
8293 warn : ( message : string ) => warnings . push ( message ) ,
94+ error : ( message : string ) => errorsLogged . push ( message ) ,
95+ trace : ( ) : void => undefined ,
8396 } ) ;
8497 injector . register ( "mobileHelper" , {
8598 isAndroidPlatform : ( platform : string ) =>
@@ -120,7 +133,10 @@ function installCompilerPackage(): string {
120133 path . join ( packageDir , "package.json" ) ,
121134 JSON . stringify ( {
122135 name : "@nativescript/compiler" ,
123- bin : { "ns-native" : "bin/ns-native.js" } ,
136+ bin : {
137+ "ns-native" : "bin/ns-native.js" ,
138+ "ns-native-retrace" : "bin/ns-native-retrace.js" ,
139+ } ,
124140 } ) ,
125141 ) ;
126142 return fs . realpathSync ( packageDir ) ;
@@ -138,6 +154,9 @@ describe("compiledReleaseService", () => {
138154 ) ;
139155 spawnCalls = [ ] ;
140156 gradleCalls = [ ] ;
157+ errorsLogged = [ ] ;
158+ gradleOutput = null ;
159+ retraceOutput = "" ;
141160 xcodebuildCalls = [ ] ;
142161 writtenFiles = { } ;
143162 warnings = [ ] ;
@@ -325,6 +344,33 @@ describe("compiledReleaseService", () => {
325344 ) ;
326345 } ) ;
327346
347+ it ( "names the TypeScript line of each Kotlin error when the Gradle build fails" , async ( ) => {
348+ const packageDir = installCompilerPackage ( ) ;
349+ const service = createService ( ) ;
350+ const projectRoot = path . join ( projectDir , "platforms" , "compiled" , "android" ) ;
351+ const kotlinError = `e: file://${ projectRoot } /src/main/kotlin/org/example/demo/Home.kt:14:9 Unresolved reference 'x'.` ;
352+ gradleOutput = [
353+ { data : "> Task :compileReleaseKotlin FAILED\n" , pipe : "stdout" } ,
354+ { data : `${ kotlinError } \n` , pipe : "stderr" } ,
355+ ] ;
356+ retraceOutput = "e: app/home.ts:7: Unresolved reference 'x'. (Home.kt:14:9)\n" ;
357+
358+ let failure : Error ;
359+ try {
360+ await service . build ( platformData ( "Android" ) , createProjectData ( ) , < any > { release : true , ...keyStore } ) ;
361+ } catch ( err ) {
362+ failure = err ;
363+ }
364+
365+ assert . match ( failure . message , / g r a d l e w f a i l e d / ) ;
366+ assert . equal ( gradleCalls [ 0 ] . options . stdio , "pipe" ) ;
367+ const retrace = spawnCalls . find ( ( c ) => c . args [ 0 ] . endsWith ( "ns-native-retrace.js" ) ) ;
368+ assert . deepStrictEqual ( retrace . args . slice ( 1 , 3 ) , [ "--build-log" , projectRoot ] ) ;
369+ assert . equal ( retrace . args [ 0 ] , path . join ( packageDir , "bin" , "ns-native-retrace.js" ) ) ;
370+ assert . equal ( writtenFiles [ retrace . args [ 3 ] ] , `${ kotlinError } \n` ) ;
371+ assert . deepStrictEqual ( errorsLogged , [ "Kotlin errors in your source:\ne: app/home.ts:7: Unresolved reference 'x'. (Home.kt:14:9)" ] ) ;
372+ } ) ;
373+
328374 it ( "builds an App Bundle for --aab" , async ( ) => {
329375 installCompilerPackage ( ) ;
330376 const service = createService ( ) ;
0 commit comments