@@ -127,6 +127,10 @@ export async function parseEclipseProject(cprojectPath: string): Promise<Eclipse
127127 if ( ! node ) throw new Error ( `not found: '<storageModule moduleId="org.eclipse.cdt.core.settings">'` ) ;
128128 cprjDom = node ;
129129
130+ const root_virtualsrcs : string [ ] = [ ] ;
131+ const root_srcdirs : string [ ] = [ ] ;
132+ const eclipseTargetList : string [ ] = [ ] ;
133+
130134 // parse all project targets
131135 for ( const ccfg of toArray ( cprjDom [ 'cconfiguration' ] ) ) {
132136
@@ -152,6 +156,8 @@ export async function parseEclipseProject(cprojectPath: string): Promise<Eclipse
152156
153157 cTarget = cTarget [ 'configuration' ] [ 0 ] ;
154158
159+ eclipseTargetList . push ( cTarget . $ [ 'name' ] ) ;
160+
155161 const tInfo : EclipseProjectTarget = {
156162 name : cTarget . $ [ 'name' ] . replace ( / \s + / g, '_' ) ,
157163 excList : [ ] ,
@@ -257,6 +263,7 @@ export async function parseEclipseProject(cprojectPath: string): Promise<Eclipse
257263 }
258264
259265 if ( cTarget . sourceEntries ) {
266+
260267 toArray ( cTarget . sourceEntries [ 0 ] . entry ) . forEach ( e => {
261268
262269 //<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="src" />
@@ -266,13 +273,13 @@ export async function parseEclipseProject(cprojectPath: string): Promise<Eclipse
266273 const srcs = cprojectDir . GetList ( SRC_FILE_FILTER , [ / ^ [ ^ \. ] .+ / ] ) ;
267274 srcs . forEach ( src => {
268275 if ( src . IsFile ( ) ) {
269- PROJ_INFO . virtualSource . files . push ( { path : src . name } ) ;
276+ root_virtualsrcs . push ( src . name ) ;
270277 } else {
271- PROJ_INFO . sourceEntries . push ( src . name ) ;
278+ root_srcdirs . push ( src . name ) ;
272279 }
273280 } ) ;
274281 } else {
275- PROJ_INFO . sourceEntries . push ( srcdir ) ;
282+ root_srcdirs . push ( srcdir ) ;
276283 }
277284 }
278285
@@ -285,6 +292,15 @@ export async function parseEclipseProject(cprojectPath: string): Promise<Eclipse
285292 }
286293 }
287294
295+ // setup root sources
296+ ArrayDelRepetition ( root_virtualsrcs ) . forEach ( srcpath => {
297+ PROJ_INFO . virtualSource . files . push ( { path : srcpath } ) ;
298+ } ) ;
299+ ArrayDelRepetition ( root_srcdirs ) . forEach ( srcdir => {
300+ if ( eclipseTargetList . includes ( srcdir ) ) return ; // skip eclipse build dir
301+ PROJ_INFO . sourceEntries . push ( srcdir ) ;
302+ } ) ;
303+
288304 const getVirtualFolder = ( rePath : string ) => {
289305
290306 rePath = rePath . trim ( )
@@ -319,6 +335,7 @@ export async function parseEclipseProject(cprojectPath: string): Promise<Eclipse
319335 } ;
320336
321337 const virtualRootList : string [ ] = [ ] ;
338+ const virtualRootMap : { [ vpath : string ] : string } = { } ;
322339
323340 // parse external source
324341 if ( _prjDom . linkedResources ) {
@@ -337,12 +354,14 @@ export async function parseEclipseProject(cprojectPath: string): Promise<Eclipse
337354 const location : string = locations [ 0 ] ;
338355 if ( typeof location != 'string' ) return ;
339356 virtualRootList . push ( vpath ) ;
340- let rootdirpath = formatFilePath ( location ) ;
341- if ( ! File . isAbsolute ( rootdirpath ) ) rootdirpath = `${ cprojectDir . path } /${ rootdirpath } ` ;
357+ const rootdirpath_ = formatFilePath ( location ) ;
358+ let rootdirfullpath = rootdirpath_ ;
359+ if ( ! File . isAbsolute ( rootdirpath_ ) ) rootdirfullpath = `${ cprojectDir . path } /${ rootdirpath_ } ` ;
342360 let vFolder = getVirtualFolder ( vpath ) ; // add this folder
343- if ( File . IsDir ( rootdirpath ) ) {
344- const files = new File ( rootdirpath ) . GetAll ( SRC_FILE_FILTER , File . EXCLUDE_ALL_FILTER ) ;
345- const srcRootDir = new File ( rootdirpath ) ;
361+ if ( File . IsDir ( rootdirfullpath ) ) {
362+ virtualRootMap [ vpath ] = File . ToUnixPath ( rootdirpath_ ) ;
363+ const files = new File ( rootdirfullpath ) . GetAll ( SRC_FILE_FILTER , File . EXCLUDE_ALL_FILTER ) ;
364+ const srcRootDir = new File ( rootdirfullpath ) ;
346365 files . forEach ( f => {
347366 let subvpath = vpath ;
348367 const dirname = srcRootDir . ToRelativePath ( f . dir ) ;
@@ -355,22 +374,36 @@ export async function parseEclipseProject(cprojectPath: string): Promise<Eclipse
355374 } ) ;
356375 }
357376
358- // del repeat args for every targets
359- for ( const target of PROJ_INFO . targets ) {
360-
361- target . excList = ArrayDelRepetition ( target . excList ) ;
362-
363- // rename virtual exclude paths
364- const excli : string [ ] = [ ] ;
365- target . excList . forEach ( p => {
377+ const completeVirtualPaths = ( pathlist : string [ ] ) : string [ ] => {
378+ return pathlist . map ( p => {
366379 if ( virtualRootList . includes ( p ) || virtualRootList . some ( e => p . startsWith ( e + '/' ) ) ) {
367- excli . push ( `${ VirtualSource . rootName } /${ p } ` ) ;
380+ return `${ VirtualSource . rootName } /${ p } ` ;
368381 } else {
369- excli . push ( p ) ;
382+ return p ;
383+ }
384+ } ) ;
385+ } ;
386+
387+ const resolveVirtualPaths = ( pathlist : string [ ] ) : string [ ] => {
388+ return pathlist . map ( p => {
389+ for ( const rootpath of virtualRootList ) {
390+ if ( ( rootpath == p || p . startsWith ( rootpath + '/' ) ) && virtualRootMap [ rootpath ] ) {
391+ return p . replace ( rootpath , virtualRootMap [ rootpath ] ) ;
392+ }
370393 }
394+ return p ;
371395 } ) ;
396+ } ;
397+
398+ // del repeat args for every targets
399+ for ( const target of PROJ_INFO . targets ) {
400+
401+ // add prefix for virtual exclude paths
402+ target . excList = completeVirtualPaths ( ArrayDelRepetition ( target . excList ) ) ;
372403
373- target . excList = excli ;
404+ // resolve virtual include paths
405+ target . globalArgs . cIncDirs = resolveVirtualPaths ( target . globalArgs . cIncDirs ) ;
406+ target . globalArgs . sIncDirs = resolveVirtualPaths ( target . globalArgs . sIncDirs ) ;
374407
375408 for ( const key in target . globalArgs ) {
376409 const obj : any = target . globalArgs ;
@@ -394,9 +427,6 @@ export async function parseEclipseProject(cprojectPath: string): Promise<Eclipse
394427
395428function parseToolOption ( optionObj : any ) : { type : string , val : string [ ] } | undefined {
396429
397- if ( optionObj . $ [ 'valueType' ] == undefined )
398- return ;
399-
400430 if ( optionObj . $ [ 'id' ] ) {
401431 // skip output args
402432 if ( [ '.converthex' , '.convertbin' , '.convert' ]
@@ -409,13 +439,13 @@ function parseToolOption(optionObj: any): { type: string, val: string[] } | unde
409439
410440 const VALUE_NAME : string = optionObj . $ [ 'name' ] || '' ;
411441 const VALUE_VAL : string = optionObj . $ [ 'value' ] || '' ;
412- const VALUE_TYPE : string = optionObj . $ [ 'valueType' ] ;
442+ const VALUE_TYPE : string | undefined = optionObj . $ [ 'valueType' ] ;
413443
414- let makeResult = ( value : string | string [ ] ) : { type : string , val : string [ ] } | undefined => {
444+ let makeResult = ( value : string | string [ ] , typ ?: string ) : { type : string , val : string [ ] } | undefined => {
415445 if ( value == '' ) return undefined ;
416446 if ( isArray ( value ) && value . length == 0 ) return undefined ;
417447 return {
418- type : VALUE_TYPE ,
448+ type : typ || VALUE_TYPE || '' ,
419449 val : isArray ( value ) ? value : [ value ]
420450 } ;
421451 } ;
@@ -429,6 +459,43 @@ function parseToolOption(optionObj: any): { type: string, val: string[] } | unde
429459 return fmt + arg ;
430460 }
431461
462+ //
463+ // match by name
464+ //
465+
466+ // <Language Standard> = option.std.gnu99
467+ if ( / L a n g u a g e S t a n d a r d / i. test ( VALUE_NAME ) ) {
468+ const m = / s t d \. ( \w + ) / . exec ( VALUE_VAL ) ;
469+ if ( m && m . length > 1 ) {
470+ const langStd = m [ 1 ] ;
471+ return makeResult ( `-std=${ langStd } ` , 'string' ) ;
472+ }
473+ }
474+
475+ if ( VALUE_NAME . includes ( '(-D)' ) ) {
476+ const li : string [ ] = [ ] ;
477+ toArray ( optionObj . listOptionValue ) . forEach ( item => li . push ( item . $ [ 'value' ] ) ) ;
478+ return makeResult ( li , 'definedSymbols' ) ;
479+ }
480+
481+ if ( VALUE_NAME . includes ( '(-I)' ) ) {
482+ const li : string [ ] = [ ] ;
483+ toArray ( optionObj . listOptionValue ) . forEach ( item => {
484+ let p = formatFilePath ( item . $ [ 'value' ] ) ;
485+ if ( p == '..' ) p = '.' ;
486+ if ( p . startsWith ( '../' ) ) p = p . substr ( 3 ) ; // for eclipse, include path is base 'Debug' folder
487+ li . push ( p ) ;
488+ } ) ;
489+ return makeResult ( li , 'includePath' ) ;
490+ }
491+
492+ //
493+ // match by type
494+ //
495+
496+ if ( VALUE_TYPE == undefined )
497+ return ;
498+
432499 if ( VALUE_TYPE == 'boolean' ) {
433500 if ( VALUE_VAL == 'true' ) {
434501 const mRes = / \( ( \- .+ ) \) / . exec ( VALUE_NAME ) ;
0 commit comments