@@ -114,6 +114,141 @@ export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor {
114114 path . skip ( ) ;
115115 } ;
116116
117+ public CallExpression : ( path : NodePath < t . CallExpression > ) => void = (
118+ path
119+ ) => {
120+ const callee = path . get ( "callee" ) ;
121+
122+ if ( callee . isMemberExpression ( ) ) {
123+ const object = callee . get ( "object" ) ;
124+ object . visit ( ) ;
125+ const property = callee . get ( "property" ) ;
126+
127+ if ( property . isIdentifier ( ) ) {
128+ const objectValue = this . _valueMap . get ( object . toString ( ) ) ;
129+ const argument = path . get ( "arguments" ) [ 0 ] ;
130+ argument . visit ( ) ;
131+ const argumentValue = < string > this . _valueMap . get ( argument . toString ( ) ) ;
132+
133+ // TODO should check if the value is actually a string
134+ if ( typeof objectValue !== "string" ) {
135+ return ;
136+ }
137+
138+ switch ( property . node . name ) {
139+ case "endsWith" : {
140+ const endOfObject =
141+ objectValue . length > argumentValue . length
142+ ? objectValue . slice ( - argumentValue . length )
143+ : objectValue ;
144+
145+ this . _isDistanceMap . set ( path . toString ( ) , true ) ;
146+
147+ if ( this . _inverted ) {
148+ if ( endOfObject === argumentValue ) {
149+ this . _valueMap . set ( path . toString ( ) , this . _normalize ( 1 ) ) ;
150+ } else {
151+ this . _valueMap . set ( path . toString ( ) , this . _normalize ( 0 ) ) ;
152+ }
153+ } else {
154+ if ( endOfObject === argumentValue ) {
155+ this . _valueMap . set ( path . toString ( ) , this . _normalize ( 0 ) ) ;
156+ } else {
157+ this . _valueMap . set (
158+ path . toString ( ) ,
159+ this . _normalize (
160+ this . _realCodedEditDistance ( endOfObject , argumentValue )
161+ )
162+ ) ;
163+ }
164+ }
165+
166+ break ;
167+ }
168+ case "startsWith" : {
169+ const startOfObject =
170+ objectValue . length > argumentValue . length
171+ ? objectValue . slice ( 0 , argumentValue . length )
172+ : objectValue ;
173+
174+ this . _isDistanceMap . set ( path . toString ( ) , true ) ;
175+
176+ if ( this . _inverted ) {
177+ if ( startOfObject === argumentValue ) {
178+ this . _valueMap . set ( path . toString ( ) , this . _normalize ( 1 ) ) ;
179+ } else {
180+ this . _valueMap . set ( path . toString ( ) , this . _normalize ( 0 ) ) ;
181+ }
182+ } else {
183+ if ( startOfObject === argumentValue ) {
184+ this . _valueMap . set ( path . toString ( ) , this . _normalize ( 0 ) ) ;
185+ } else {
186+ this . _valueMap . set (
187+ path . toString ( ) ,
188+ this . _normalize (
189+ this . _realCodedEditDistance ( startOfObject , argumentValue )
190+ )
191+ ) ;
192+ }
193+ }
194+
195+ break ;
196+ }
197+ case "includes" : {
198+ this . _isDistanceMap . set ( path . toString ( ) , true ) ;
199+
200+ if ( this . _inverted ) {
201+ if ( objectValue . includes ( argumentValue ) ) {
202+ this . _valueMap . set ( path . toString ( ) , this . _normalize ( 1 ) ) ;
203+ } else {
204+ this . _valueMap . set ( path . toString ( ) , this . _normalize ( 0 ) ) ;
205+ }
206+ } else {
207+ if ( objectValue . includes ( argumentValue ) ) {
208+ this . _valueMap . set ( path . toString ( ) , this . _normalize ( 0 ) ) ;
209+ } else {
210+ // search
211+ if ( objectValue . length > argumentValue . length ) {
212+ let minValue = Number . MAX_VALUE ;
213+ for (
214+ let start = 0 ;
215+ start < objectValue . length - argumentValue . length ;
216+ start ++
217+ ) {
218+ const substring = objectValue . slice (
219+ start ,
220+ argumentValue . length
221+ ) ;
222+
223+ minValue = Math . min (
224+ minValue ,
225+ this . _realCodedEditDistance ( substring , argumentValue )
226+ ) ;
227+ }
228+
229+ this . _valueMap . set (
230+ path . toString ( ) ,
231+ this . _normalize ( minValue )
232+ ) ;
233+ } else {
234+ this . _valueMap . set (
235+ path . toString ( ) ,
236+ this . _normalize (
237+ this . _realCodedEditDistance ( objectValue , argumentValue )
238+ )
239+ ) ;
240+ }
241+ }
242+ }
243+
244+ break ;
245+ }
246+ // No default
247+ }
248+ }
249+ }
250+ } ;
251+
117252 public Literal : ( path : NodePath < t . Literal > ) => void = ( path ) => {
118253 switch ( path . node . type ) {
119254 case "NullLiteral" : {
@@ -572,12 +707,12 @@ export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor {
572707 "|>" ,
573708 ] . includes ( operator )
574709 ) {
575- this . _valueMap . set ( path . toString ( ) , this . _normalize ( < number > value ) ) ;
710+ value = this . _normalize ( < number > value ) ;
576711 this . _isDistanceMap . set ( path . toString ( ) , true ) ;
577712 } else {
578- this . _valueMap . set ( path . toString ( ) , value ) ;
579713 this . _isDistanceMap . set ( path . toString ( ) , false ) ;
580714 }
715+ this . _valueMap . set ( path . toString ( ) , value ) ;
581716
582717 path . skip ( ) ;
583718 } ;
@@ -689,7 +824,7 @@ export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor {
689824 return mi ;
690825 }
691826
692- protected _realCodedEditDistance ( s : string , t : string ) {
827+ public _realCodedEditDistance ( s : string , t : string ) {
693828 const d : number [ ] [ ] = [ ] ; // matrix
694829 let index ; // iterates through s
695830 let index_ ; // iterates through t
@@ -756,7 +891,7 @@ export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor {
756891 ! this . _stringAlphabet . includes ( s_index )
757892 ) {
758893 BranchDistanceVisitor . LOGGER . warn (
759- `cannot search for character missing from the sampling alphabet one of these is missing: ${ t_index } , ${ s_index } `
894+ `Cannot search for character missing from the sampling alphabet one of these is missing: ${ t_index } , ${ s_index } `
760895 ) ;
761896 cost = Number . MAX_VALUE ;
762897 } else {
@@ -765,7 +900,7 @@ export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor {
765900 this . _stringAlphabet . indexOf ( t_index )
766901 ) ;
767902 }
768- // cost = this._normalize(cost);
903+ cost = this . _normalize ( cost ) ;
769904 }
770905
771906 // Step 6
0 commit comments