@@ -221,6 +221,57 @@ describe('Parts', () => {
221221
222222 const _handler : ValueHandler = new ValueHandler ( { } ) ;
223223
224+ // is_term メソッドを公開してテスト用に利用
225+ class TermParser extends AttributeParser {
226+ constructor ( handler : BaseHandler | null , stream : ParserStream ) {
227+ super ( handler , stream ) ;
228+ }
229+
230+ public is_term ( ) : boolean {
231+ return super . is_term ( ) ;
232+ }
233+
234+ public is_factor ( ) : boolean {
235+ return super . is_factor ( ) ;
236+ }
237+ }
238+
239+ // is_expr メソッドも公開してより詳細なテスト
240+ class ExprParser extends AttributeParser {
241+ constructor ( handler : BaseHandler | null , stream : ParserStream ) {
242+ super ( handler , stream ) ;
243+ }
244+
245+ public is_expr ( ) : boolean {
246+ return super . is_expr ( ) ;
247+ }
248+
249+ public is_term ( ) : boolean {
250+ return super . is_term ( ) ;
251+ }
252+
253+ public is_factor ( ) : boolean {
254+ return super . is_factor ( ) ;
255+ }
256+ }
257+
258+ // parser.ts:213-214の確実なカバレッジ: is_factor()がfalseを返すケース
259+ // 重要: 演算子の後にis_factor()がfalseになるが、すでにresult=trueのケース
260+ const testCases = [
261+ "3*" , "4/" , "5*xyz" , "6/xyz" , // xyzは無効なfactor
262+ "7* " , "8/ " , "9*!" , "10/!" // スペースや記号は無効なfactor
263+ ] ;
264+ testCases . forEach ( testCase => {
265+ expect ( new ExprParser ( _handler , new ParserStream ( testCase ) ) . is_expr ( ) ) . toBe ( true ) ;
266+ } ) ;
267+
268+ // 未カバー箇所のテスト: 乗算・除算演算子の後にfactorが続かない場合
269+ // parser.ts:213-214の完全カバレッジのため、is_factor()がfalseになるケースをテスト
270+ expect ( new TermParser ( _handler , new ParserStream ( "1*(" ) ) . is_term ( ) ) . toBe ( true ) ; // (で始まるが不完全
271+ expect ( new TermParser ( _handler , new ParserStream ( "1/+" ) ) . is_term ( ) ) . toBe ( true ) ; // +は無効なfactor開始
272+ expect ( new TermParser ( _handler , new ParserStream ( "1* " ) ) . is_term ( ) ) . toBe ( true ) ; // スペースの後に何もない
273+ expect ( new TermParser ( _handler , new ParserStream ( "1/ " ) ) . is_term ( ) ) . toBe ( true ) ; // 複数スペースの後に何もない
274+
224275 class FormParser extends AttributeParser {
225276
226277 constructor ( handler : BaseHandler | null , stream : ParserStream ) {
@@ -318,6 +369,73 @@ describe('ESModule', () => {
318369 expect ( AttrPath . traverse ( { } , '.path' ) ) . toBeUndefined ( ) ;
319370 } ) ;
320371
372+ it ( 'Performance' , ( ) => {
373+
374+ const value = {
375+ children : {
376+ john : {
377+ hobby : [ { name : "Cycling" } , { name : "Dance" } ] ,
378+ pet : [ { type : "dog" , name : "Max" } ]
379+ } ,
380+ "花子" : {
381+ hobby : [ { name : "Squash" } ] ,
382+ pet : [ { type : "cat" , name : "Chloe" } ]
383+ }
384+ }
385+ } ;
386+
387+ const start = process . hrtime ( ) ;
388+ AttrPath . traverse ( value , '.children' )
389+ AttrPath . traverse ( value , '.children.john' )
390+ AttrPath . traverse ( value , '.children.john.hobby' )
391+ AttrPath . traverse ( value , '.children.john.hobby[0]' )
392+ AttrPath . traverse ( value , '.children.john.hobby[0].name' )
393+ AttrPath . traverse ( value , '.children.john.hobby[0a].name' )
394+ AttrPath . traverse ( value , '.children.john.hobby[1].name' )
395+ AttrPath . traverse ( value , '.children.john.pet[0].type' )
396+ AttrPath . traverse ( value , '.children.john.pet[0].name' )
397+ AttrPath . traverse ( value , '.children.花子.hobby[0].name' )
398+ AttrPath . traverse ( value , '.children.花子.pet[0].type' )
399+ AttrPath . traverse ( value , '.children.花子.pet[0].name' )
400+ AttrPath . traverse ( value , '.children.john.hobby["0"].name' )
401+ AttrPath . traverse ( value , '.children.john.hobby["0"].name' , "no name" )
402+ AttrPath . traverse ( value , '.children["john"].hobby[0].name' )
403+ AttrPath . traverse ( value , '.children["john"].hobby[0]["name"]' )
404+ AttrPath . traverse ( value , '["children"]["john"].hobby[0].name' )
405+ AttrPath . traverse ( value , '.children["john"].hobby[0].name' )
406+ AttrPath . traverse ( value , '["children"]["john"]["hobby"][0]["name"]' )
407+ AttrPath . traverse ( value , '["children"]["john"]["hobby"][0].["name"]' )
408+ AttrPath . traverse ( value , '["children"]["john"]["hobby"][0]["name"]' )
409+ AttrPath . traverse ( value , '.children["john"].hobby[1].name' )
410+
411+ AttrPath . traverse ( [ 1 ] , '[0]' )
412+ AttrPath . traverse ( AttrPath . traverse ( value , '.children.john' ) , '.hobby' )
413+ AttrPath . traverse ( null , '.path' )
414+ AttrPath . traverse ( null , '.path.path' )
415+ AttrPath . traverse ( null , '["path"]' )
416+ AttrPath . traverse ( null , '.path["path"]' )
417+ AttrPath . traverse ( null , '["0"]' )
418+ AttrPath . traverse ( null , '[0]' )
419+ AttrPath . traverse ( [ 1 , 2 , 3 ] , '[3]' )
420+
421+ AttrPath . traverse ( undefined , '.path' )
422+
423+ AttrPath . traverse ( false , '.path' )
424+ AttrPath . traverse ( true , '.path' )
425+ AttrPath . traverse ( NaN , '.path' )
426+ AttrPath . traverse ( Infinity , '.path' )
427+ AttrPath . traverse ( 0 , '.path' )
428+ AttrPath . traverse ( - 1 , '.path' )
429+ AttrPath . traverse ( "" , '.path' )
430+ AttrPath . traverse ( "1" , '.path' )
431+ AttrPath . traverse ( [ 1 ] , '.path' )
432+
433+ AttrPath . traverse ( { } , '.path' )
434+
435+ const end = process . hrtime ( start ) ;
436+ console . log ( ( end [ 1 ] / 1000000 ) + "ms" ) ;
437+ } ) ;
438+
321439 it ( 'Key' , ( ) => {
322440
323441 const value = {
@@ -497,14 +615,12 @@ describe('ESModule', () => {
497615 } ) ;
498616
499617 it ( 'Valid' , ( ) => {
500-
501618 expect ( AttrPath . is_valid ( '[1]' ) ) . toBe ( true ) ;
502619 expect ( AttrPath . is_valid ( '["john"]' ) ) . toBe ( true ) ;
503620 expect ( AttrPath . is_valid ( '.children["john"].hobby[1].name' ) ) . toBe ( true ) ;
504621 expect ( AttrPath . is_valid ( '.children["john"].hobby[1a].name' ) ) . toBe ( false ) ;
505622 expect ( AttrPath . is_valid ( '.children["john"].hobby["1"].name' ) ) . toBe ( false ) ;
506623 expect ( AttrPath . is_valid ( 'this.name' ) ) . toBe ( false ) ;
507-
508624 } ) ;
509625
510626 it ( 'Classes' , ( ) => {
@@ -539,6 +655,7 @@ describe('ESModule', () => {
539655 return new AttributeParser ( null , new ParserStream ( path ) ) . parse_path ( ) ;
540656 }
541657
658+
542659 expect ( Traverse ( value , '.children' ) ) . toStrictEqual ( { "john" : { "hobby" : [ { "name" : "Cycling" } , { "name" : "Dance" } ] , "pet" : [ { "type" : "dog" , "name" : "Max" } ] } , "花子" : { "hobby" : [ { "name" : "Squash" } ] , "pet" : [ { "type" : "cat" , "name" : "Chloe" } ] } , _jack$ : { _hobby$ : [ { $name : "Fury" } ] , $pet$ : [ { type_ : "bat" , $name : "Dread" } ] } } ) ;
543660 expect ( Traverse ( value , '.children.john' ) ) . toStrictEqual ( { "hobby" : [ { "name" : "Cycling" } , { "name" : "Dance" } ] , "pet" : [ { "type" : "dog" , "name" : "Max" } ] } ) ;
544661 expect ( Traverse ( value , '.children.john.hobby' ) ) . toStrictEqual ( [ { "name" : "Cycling" } , { "name" : "Dance" } ] ) ;
0 commit comments