import TokenStream from '../../../utils/jass2/tokenstream' ; import { IniSection , IniFile } from '../../ini/file' ; /**
 * A standard object mapping strings to strings.
 */ export type StringObject = { [ key ] : string ; } ; export type FunctionSignature = { args : string [ ] ; scriptName : string | null ; returnType : string | null ; } ; /**
 * A standard object mapping strings to function signatures and an optional Jass name.
 */ export type FunctionObject = { [ key ] : FunctionSignature ; } ; /**
 * Trigger data needed to load a WTG file.
 */ export class TriggerData { types : StringObject = { } ; functions : FunctionObject [ ] = [ { } , { } , { } , { } ] ; presets : StringObject = { } ; externalTypes : StringObject = { } ; externalFunctions : FunctionObject [ ] = [ { } , { } , { } , { } ] ; externalPresets : StringObject = { } ; addTriggerData ( buffer , isExternal ) { let types = this . types ; let functions = this . functions ; let presets = this . presets ; if ( isExternal ) { types = this . externalTypes ; functions = this . externalFunctions ; presets = this . externalPresets ; } const triggerData = new IniFile ( ) ; triggerData . load ( buffer ) ; let section = triggerData . getSection ( 'TriggerTypes' ) ; if ( section ) { this . addTriggerTypes ( types , section ) ; } section = triggerData . getSection ( 'TriggerEvents' ) ; if ( section ) { this . addTriggerDataFunctions ( functions [ 0 ] , section , 1 ) ; } section = triggerData . getSection ( 'TriggerConditions' ) ; if ( section ) { this . addTriggerDataFunctions ( functions [ 1 ] , section , 1 ) ; } section = triggerData . getSection ( 'TriggerActions' ) ; if ( section ) { this . addTriggerDataFunctions ( functions [ 2 ] , section , 1 ) ; } section = triggerData . getSection ( 'TriggerCalls' ) ; if ( section ) { this . addTriggerDataFunctions ( functions [ 3 ] , section , 3 ) ; } section = triggerData . getSection ( 'TriggerParams' ) ; if ( section ) { this . addTriggerDataPresets ( presets , section ) ; } } addTriggerTypes ( types , section ) { for ( const [ key , value ] of section ) { const tokens = value . split ( ',' ) ; types [ key . toLowerCase ( ) ] = tokens [ 4 ] || '' ; } } addTriggerDataFunctions ( functions , section , skipped ) { for ( const [ key , value ] of section ) { if ( key [ 0 ] !== '_' ) { const tokens = value . split ( ',' ) ; const args = [ ] ; const scriptName = < string > section . get ( `_${ key }_scriptname` ) || null ; let returnType = null ; if ( skipped === 3 ) { returnType = tokens [ 2 ] ; } for ( let i = skipped , l = tokens . length ; i < l ; i ++ ) { const token = tokens [ i ] ; if ( Number . isNaN ( parseFloat ( token ) ) && token !== 'nothing' && token !== '' ) { args . push ( token ) ; } } functions [ key . toLowerCase ( ) ] = { args , scriptName , returnType } ; } } } addTriggerDataPresets ( presets , section ) { for ( const [ key , value ] of section ) { const tokens = value . split ( ',' ) ; presets [ key . toLowerCase ( ) ] = tokens [ 2 ] . replace ( /"/g , '' ) . replace ( /`/g , '"' ) ; } } addJassFunctions ( jass ) { const stream = new TokenStream ( jass ) ; let token ; while ( ( token = stream . read ( ) ) !== undefined ) { if ( token === 'native' || token === 'function' ) { const scriptName = stream . read ( ) ; if ( scriptName ) { token = stream . read ( ) ; if ( token === 'takes' ) { const args = [ ] ; const token = stream . readSafe ( ) ; if ( token !== 'nothing' ) { args . push ( token ) ; stream . readSafe ( ) ; while ( stream . read ( ) === ',' ) { args . push ( stream . readSafe ( ) ) ; stream . readSafe ( ) ; } } else { stream . read ( ) ; } let returnType = stream . readSafe ( ) ; if ( returnType === 'nothing' ) { returnType = null ; } const name = scriptName . toLowerCase ( ) ; const signature = { args , scriptName , returnType } ; this . externalFunctions [ 2 ] [ name ] = signature ; if ( returnType !== 'nothing' ) { this . externalFunctions [ 3 ] [ name ] = signature ; } } } } } } /**
     * Given a type, return its base type.
     *
     * Returns the given type if its not a child type.
     */ getBaseType ( type ) { type = type . toLowerCase ( ) ; let base = this . types [ type ] ; if ( base === undefined ) { base = this . externalTypes [ type ] ; } if ( base === '' || base === undefined ) { return type ; } return base ; } isBaseFunction ( type , name ) { name = name . toLowerCase ( ) ; if ( this . functions [ type ] [ name ] ) { return true ; } return false ; } /**
     * Gets the signature of the given function.
     */ getFunction ( type , name ) { name = name . toLowerCase ( ) ; let args = this . functions [ type ] [ name ] ; if ( ! args ) { args = this . externalFunctions [ type ] [ name ] ; } return args ; } /**
     * Get the type of a function given its name.
     * Returns -1 if the function isn't recognized.
     */ getFunctionType ( name ) { name = name . toLowerCase ( ) ; const functions = this . functions ; for ( let i = 0 ; i < 4 ; i ++ ) { if ( functions [ i ] [ name ] ) { return i ; } } return - 1 ; } /**
     * Gets a preset value.
     */ getPreset ( name ) { name = name . toLowerCase ( ) ; let preset = this . presets [ name ] ; if ( preset === undefined ) { preset = this . externalPresets [ name ] ; } return preset ; } /**
     * Is the given preset a custom or standard one?
     */ isCustomPreset ( name ) { name = name . toLowerCase ( ) ; if ( this . presets [ name ] !== undefined ) { return false ; } if ( this . externalPresets [ name ] !== undefined ) { return true ; } throw new Error ( `Failed to find a preset: ${ name }` ) ; } }