import Variable , { VariableLocation } from '../variable' ; import Color from '../../colors/color' ; import VariablesStore from '../variable-store' ; import ColorExtractor from '../../colors/color-extractor' ; import { DocumentLine , LineExtraction , flattenLineExtractionsFlatten } from '../../util/color-util' ; export interface IStategyRegexpResultExtractor { getVariableNameFromDeclaration ( match ) : string ; getVariableNameFromUses ( match ) : string [ ] ; getVariableNameFromUse ( match ) : string ; } export default class VariableStrategy { constructor ( public name , private DECLARATION_REGEXP , private USES_REGEXP , private USE_REGEXP , private regexpExtractor ) { } protected store : VariablesStore = new VariablesStore ( ) ; public async extractDeclarations ( fileName , fileLines ) { return fileLines . map ( ( { text , line } ) => this . __extractDeclarations ( fileName , text , line ) ) . length ; } public __extractDeclarations ( fileName , text , line ) { let match = null ; while ( ( match = this . DECLARATION_REGEXP . exec ( text ) ) !== null ) { const varName = this . regexpExtractor . getVariableNameFromDeclaration ( match ) ; const color = ColorExtractor . extractOneColor ( text . slice ( match . index + match [ 0 ] . length ) . trim ( ) ) || this . extractVariable ( fileName , text . slice ( match . index + match [ 0 ] . length ) . trim ( ) ) ; if ( this . store . has ( varName , fileName , line ) ) { const decoration = this . store . findDeclaration ( varName , fileName , line ) ; decoration . update ( < Color > color ) ; } else { const variable = new Variable ( varName , < Color > color , { fileName , line , position : match . index } , this . name ) ; this . store . addEntry ( varName , variable ) ; } } } public extractVariables ( fileName , fileLines ) { const variables = fileLines . map ( ( { line , text } ) => { let match = null ; const colors = [ ] ; while ( ( match = this . USES_REGEXP . exec ( text ) ) !== null ) { const [ varName , extendedVarName , spaces ] = this . regexpExtractor . getVariableNameFromUses ( match ) ; const spacesCount = ( spaces || '' ) . length ; const location = { fileName , line , position : spacesCount + match . index } ; const variable = new Variable ( varName , new Color ( extendedVarName || varName , spacesCount + match . index , null , null ) , location , this . name ) ; colors . push ( variable ) ; } return { line , colors } ; } ) ; return flattenLineExtractionsFlatten ( variables ) ; } extractVariable ( fileName , text ) { const match = text . match ( this . USE_REGEXP ) ; let variable ; if ( match ) { const varName = this . regexpExtractor . getVariableNameFromUse ( match ) ; variable = this . store . findClosestDeclaration ( varName , fileName ) ; return variable ? variable . color : undefined ; } } param { Variable } variable returns { Color | null } public getVariableValue ( variable ) { let color = null ; if ( this . store . has ( variable . name ) === true ) { let declaration = this . store . findClosestDeclaration ( variable . name , variable . location . fileName ) ; if ( declaration . color === undefined ) { declaration = this . store . findClosestDeclaration ( variable . name , '.' ) ; } if ( declaration . color ) { color = new Color ( variable . color . value , variable . location . position , declaration . color . rgb , declaration . color . alpha ) ; } } return color ; } variablesCount ( ) { return this . store . count ; } deleteVariable ( fileName , line ) { this . store . delete ( null , fileName , line ) ; } }