@@ -400,7 +400,53 @@ def _run_benchmark(suite, name, args, vmargs):
400400 mx .abort ("Gate for {} benchmark '{}' failed!" .format (suite , name ))
401401 return exit_code , suite , results
402402
403+ def _check_forbidden_imports (projects , package_substrings , exceptions = None ):
404+ """
405+ Checks Java source files in `projects` to ensure there is no import from
406+ a class in a package whose name does not match `package_substrings`
407+ of a package whose name matches `package_substrings`.
408+
409+ :param projects: list of JavaProjects
410+ :param package_substrings: package name substrings
411+ :param exceptions: set of unqualified Java source file names for which a failing
412+ check produces a warning instead of an abort
413+ """
414+ # Assumes package name components start with lower case letter and
415+ # classes start with upper-case letter
416+ importStatementRe = re .compile (r'\s*import\s+(?:static\s+)?([a-zA-Z\d_$\.]+\*?)\s*;\s*' )
417+ importedRe = re .compile (r'((?:[a-z][a-zA-Z\d_$]*\.)*[a-z][a-zA-Z\d_$]*)\.(?:(?:[A-Z][a-zA-Z\d_$]*)|\*)' )
418+ for project in projects :
419+ for source_dir in project .source_dirs ():
420+ for root , _ , files in os .walk (source_dir ):
421+ java_sources = [name for name in files if name .endswith ('.java' ) and name != 'module-info.java' ]
422+ if len (java_sources ) != 0 :
423+ java_package = root [len (source_dir ) + 1 :].replace (os .sep , '.' )
424+ if not any ((s in java_package for s in package_substrings )):
425+ for n in java_sources :
426+ java_source = join (root , n )
427+ with open (java_source ) as fp :
428+ for i , line in enumerate (fp ):
429+ m = importStatementRe .match (line )
430+ if m :
431+ imported = m .group (1 )
432+ m = importedRe .match (imported )
433+ lineNo = i + 1
434+ if not m :
435+ mx .abort (java_source + ':' + str (lineNo ) + ': import statement does not match expected pattern:\n ' + line )
436+ imported_package = m .group (1 )
437+ for s in package_substrings :
438+ if s in imported_package :
439+ message = f'{ java_source } :{ lineNo } : forbidden import of a "{ s } " package: { imported_package } \n { line } '
440+ if exceptions and n in exceptions :
441+ mx .warn (message )
442+ else :
443+ mx .abort (message )
444+
403445def compiler_gate_runner (suites , unit_test_runs , bootstrap_tests , tasks , extraVMarguments = None , extraUnitTestArguments = None ):
446+ with Task ('CheckForbiddenImports:Compiler' , tasks , tags = ['style' ]) as t :
447+ # Ensure HotSpot-independent compiler classes do not import HotSpot-specific classes
448+ if t : _check_forbidden_imports ([mx .project ('jdk.internal.vm.compiler' )], ('hotspot' , 'libgraal' ))
449+
404450 with Task ('JDK_java_base_test' , tasks , tags = ['javabasetest' ], report = True ) as t :
405451 if t : java_base_unittest (_remove_empty_entries (extraVMarguments ) + [])
406452
0 commit comments