import { TemplateScope } from "../documents/templates/scopes/TemplateScope" ; import { IVariableDefinition } from '../documents/templates/VariableDefinition' ; import { FunctionCallValue , PropertyAccess , TleVisitor , Value } from "../language/expressions/TLE" ; import { Issue } from "../language/Issue" ; import { IssueKind } from "../language/IssueKind" ; import * as Json from '../language/json/JSON' ; /**
 * A TLE visitor that finds references to variable properties that aren't defined in the variable's value
 */ export class UndefinedVariablePropertyVisitor extends TleVisitor { private _errors : Issue [ ] = [ ] ; constructor ( private _scope ) { super ( ) ; } public get errors ( ) : Issue [ ] { return this . _errors ; } public visitPropertyAccess ( tlePropertyAccess ) { if ( tlePropertyAccess . nameToken ) { const functionSource = tlePropertyAccess . functionSource ; if ( functionSource ) { const variableProperty = this . _scope . getVariableDefinitionFromFunctionCall ( functionSource ) ; if ( variableProperty ) { const variableDefinition = Json . asObjectValue ( variableProperty . value ) ; const sourcesNameStack = tlePropertyAccess . sourcesNameStack ; if ( variableDefinition ) { const sourcePropertyDefinition = Json . asObjectValue ( variableDefinition . getPropertyValueFromStack ( sourcesNameStack ) ) ; if ( sourcePropertyDefinition && ! sourcePropertyDefinition . hasProperty ( tlePropertyAccess . nameToken . stringValue ) ) { this . addIssue ( tlePropertyAccess ) ; } } else if ( sourcesNameStack . length === 0 ) { this . addIssue ( tlePropertyAccess ) ; } } } } super . visitPropertyAccess ( tlePropertyAccess ) ; } private addIssue ( tlePropertyAccess ) { const nameToken = tlePropertyAccess . nameToken ; const propertyName = nameToken ? nameToken . stringValue : "(unknown)" ; const sourceString = tlePropertyAccess . source . toString ( ) ; const span = nameToken ? nameToken . span : tlePropertyAccess . getSpan ( ) ; this . _errors . push ( new Issue ( span , `Property "${ propertyName }" is not a defined property of "${ sourceString }".` , IssueKind . undefinedVarProp ) ) ; } public static visit ( tleValue , scope ) { const visitor = new UndefinedVariablePropertyVisitor ( scope ) ; if ( tleValue ) { tleValue . accept ( visitor ) ; } return visitor ; } }