question: public void step3 ( Map < String , String > fileNameToPackageName , Map < String , List < FunDef > > fileNameToFunctions ) throws SyntaxException { for ( STypeDef sTypeDef : typeDefSet ) { if ( sTypeDef instanceof SClassDef ) { List < STypeDef > circularRecorder = new ArrayList < > ( ) ; SClassDef parent = ( ( SClassDef ) sTypeDef ) . parent ( ) ; while ( parent != null ) { circularRecorder . add ( parent ) ; if ( parent . equals ( sTypeDef ) ) { err . SyntaxException ( "circular inheritance " + circularRecorder , LineCol . SYNTHETIC ) ; return ; } parent = parent . parent ( ) ; } circularRecorder . clear ( ) ; } else if ( sTypeDef instanceof SInterfaceDef ) { SInterfaceDef i = ( SInterfaceDef ) sTypeDef ; checkInterfaceCircularInheritance ( i , i . superInterfaces ( ) , new ArrayList < > ( ) ) ; } else { throw new LtBug ( "wrong STypeDefType " + sTypeDef . getClass ( ) ) ; } } for ( STypeDef sTypeDef : typeDefSet ) { checkOverrideAllMethods ( sTypeDef ) ; } for ( String fileName : mapOfStatements . keySet ( ) ) { List < Import > imports = fileNameToImport . get ( fileName ) ; String pkg = fileNameToPackageName . get ( fileName ) ; List < FunDef > functionDefs = fileNameToFunctions . get ( fileName ) ; for ( FunDef fun : functionDefs ) { STypeDef type = getTypeWithAccess ( fun . superType , imports ) ; if ( ! ( type instanceof SClassDef || type instanceof SInterfaceDef ) ) { err . SyntaxException ( "function super type should be functional interfaces or functional abstract classes" , fun . superType . line_col ( ) ) ; return ; } SConstructorDef [ ] zeroParamConstructor = new SConstructorDef [ 1 ] ; SMethodDef [ ] methodToOverride = new SMethodDef [ 1 ] ; if ( ! getMethodForLambda ( type , zeroParamConstructor , methodToOverride ) ) { err . SyntaxException ( "function super type should be functional interfaces or functional abstract classes" , fun . superType . line_col ( ) ) ; return ; } SClassDef sClassDef = ( SClassDef ) types . get ( pkg + fun . name ) ; parseAnnos ( fun . annos , sClassDef , imports , ElementType . TYPE , Arrays . asList ( ElementType . METHOD , ElementType . CONSTRUCTOR ) ) ; if ( zeroParamConstructor [ 0 ] == null ) { sClassDef . setParent ( getObject_Class ( ) ) ; assert type instanceof SInterfaceDef ; sClassDef . superInterfaces ( ) . add ( ( SInterfaceDef ) type ) ; } else { sClassDef . setParent ( ( SClassDef ) zeroParamConstructor [ 0 ] . declaringType ( ) ) ; } SConstructorDef cons = new SConstructorDef ( LineCol . SYNTHETIC ) ; parseAnnos ( fun . annos , cons , imports , ElementType . CONSTRUCTOR , Arrays . asList ( ElementType . TYPE , ElementType . METHOD ) ) ; cons . setDeclaringType ( sClassDef ) ; sClassDef . constructors ( ) . add ( cons ) ; if ( zeroParamConstructor [ 0 ] == null ) { zeroParamConstructor [ 0 ] = getObject_Class ( ) . constructors ( ) . get ( 0 ) ; } cons . statements ( ) . add ( new Ins . InvokeSpecial ( new Ins . This ( sClassDef ) , zeroParamConstructor [ 0 ] , LineCol . SYNTHETIC ) ) ; cons . modifiers ( ) . add ( SModifier . PUBLIC ) ; SMethodDef method = new SMethodDef ( LineCol . SYNTHETIC ) ; method . setDeclaringType ( sClassDef ) ; method . setReturnType ( getRealReturnType ( methodToOverride [ 0 ] . getReturnType ( ) , true ) ) ; method . setName ( methodToOverride [ 0 ] . name ( ) ) ; sClassDef . methods ( ) . add ( method ) ; parseAnnos ( fun . annos , method , imports , ElementType . METHOD , Arrays . asList ( ElementType . TYPE , ElementType . CONSTRUCTOR ) ) ; method . modifiers ( ) . add ( SModifier . PUBLIC ) ; parseParameters ( fun . params , fun . params . size ( ) , method , imports , false ) ; methodToStatements . put ( method , fun . statements ) ; checkOverrideAllMethods ( sClassDef ) ; } } for ( STypeDef typeDef : typeDefSet ) { for ( SAnno anno : typeDef . annos ( ) ) { if ( anno . type ( ) . fullName ( ) . equals ( "java.lang.FunctionalInterface" ) ) { final String msg = typeDef + " is not a functional interface" ; if ( typeDef instanceof SInterfaceDef ) { if ( ! getMethodForLambda ( typeDef , new SConstructorDef [ 1 ] , new SMethodDef [ 1 ] ) ) { err . SyntaxException ( msg , typeDef . line_col ( ) ) ; return ; } } else { err . SyntaxException ( msg , typeDef . line_col ( ) ) ; return ; } } else if ( anno . type ( ) . fullName ( ) . equals ( "lt.lang.FunctionalAbstractClass" ) ) { final String msg = typeDef + " is not a functional abstract class" ; if ( typeDef instanceof SClassDef ) { if ( ! getMethodForLambda ( typeDef , new SConstructorDef [ 1 ] , new SMethodDef [ 1 ] ) ) { err . SyntaxException ( msg , typeDef . line_col ( ) ) ; return ; } } else { err . SyntaxException ( msg , typeDef . line_col ( ) ) ; return ; } } } List < SMethodDef > methods ; if ( typeDef instanceof SClassDef ) methods = ( ( SClassDef ) typeDef ) . methods ( ) ; else methods = ( ( SInterfaceDef ) typeDef ) . methods ( ) ; for ( SMethodDef method : methods ) { for ( SAnno anno : method . annos ( ) ) { if ( anno . type ( ) . fullName ( ) . equals ( "java.lang.Override" ) ) { if ( method . overRide ( ) . isEmpty ( ) ) { err . SyntaxException ( method + " doesn't override any method" , method . line_col ( ) ) ; return ; } } } } } for ( STypeDef typeDef : typeDefSet ) { if ( typeDef instanceof SClassDef ) { SClassDef cls = ( SClassDef ) typeDef ; if ( cls . isDataClass ( ) ) { fillMethodsIntoDataClass ( cls ) ; } } } }
target:  ========step 3======== check circular inheritance