diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 000000000..b416dbb9d --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,56 @@ +max_width = 100 +hard_tabs = false +tab_spaces = 4 +newline_style = "Unix" +use_small_heuristics = "Default" +indent_style = "Block" +wrap_comments = false +comment_width = 80 +normalize_comments = false +format_strings = false +empty_item_single_line = true +struct_lit_single_line = true +fn_single_line = false +where_single_line = false +imports_indent = "Block" +imports_layout = "Mixed" +merge_imports = false +reorder_imports = true +reorder_modules = true +reorder_impl_items = false +type_punctuation_density = "Wide" +space_before_colon = false +space_after_colon = true +spaces_around_ranges = false +binop_separator = "Front" +remove_nested_parens = true +combine_control_expr = true +struct_field_align_threshold = 0 +match_arm_blocks = true +force_multiline_blocks = false +fn_args_density = "Tall" +brace_style = "SameLineWhere" +control_brace_style = "AlwaysSameLine" +trailing_semicolon = true +trailing_comma = "Vertical" +match_block_trailing_comma = false +blank_lines_upper_bound = 1 +blank_lines_lower_bound = 0 +merge_derives = true +use_try_shorthand = false +use_field_init_shorthand = false +force_explicit_abi = true +condense_wildcard_suffixes = false +color = "Auto" +required_version = "0.8.2" +unstable_features = false +disable_all_formatting = false +skip_children = false +hide_parse_errors = false +error_on_line_overflow = false +error_on_unformatted = false +report_todo = "Never" +report_fixme = "Never" +ignore = [] +emit_mode = "Files" +make_backup = false diff --git a/.travis.yml b/.travis.yml index 70933f9c0..82d098f9e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,8 @@ cache: dist: trusty sudo: required language: generic +env: + - RUSTUP_TOOLCHAIN=$TRAVIS_RUST_VERSION install: - cd .. - gem install mdl @@ -31,6 +33,7 @@ install: - mx sforceimports # the style gate needs the full commit history for checking copyright years - test "$GATE_TAGS" != "style" || git fetch --unshallow + - test "$GATE_TAGS" != "style" || rustup component add rustfmt-preview --toolchain=$TRAVIS_RUST_VERSION script: - cd ../llvmDir - ln -s /usr/bin/clang-$LLVM_VER clang @@ -110,6 +113,8 @@ matrix: - libc++1 - libc++-dev - env: LLVM_VER=3.8 GATE_TAGS='style' + language: rust + rust: nightly addons: apt: packages: diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index 3bd80220b..d1d518c41 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -111,6 +111,11 @@ '4.0', ] +# the file paths that we want to check with rustfmt +rustfmtCheckPaths = [ + join(_testDir, "com.oracle.truffle.llvm.tests.sulongrust") +] + def _unittest_config_participant(config): (vmArgs, mainClass, mainClassArgs) = config testSuitePath = mx_subst.path_substitutions.substitute('') @@ -134,6 +139,8 @@ def _sulong_gate_runner(args, tasks): t.abort('Copyright errors found. Please run "mx checkcopyrights --primary -- --fix" to fix them.') with Task('ClangFormat', tasks, tags=['style', 'clangformat']) as t: if t: clangformatcheck() + with Task('Rustfmt', tasks, tags=['style', 'rustfmt']) as t: + if t: rustfmtcheck() with Task('TestBenchmarks', tasks, tags=['benchmarks', 'sulongMisc']) as t: if t: mx_testsuites.runSuite('shootout') with Task('TestTypes', tasks, tags=['type', 'sulongMisc']) as t: @@ -217,14 +224,22 @@ def runLLVMUnittests(unittest_runner): def clangformatcheck(args=None): """ Performs a format check on the include/truffle.h file """ for f in clangFormatCheckPaths: - checkCFiles(f) + checkFiles(f, checkCFile, ['.c', '.cpp', '.h', '.hpp']) -def checkCFiles(targetDir): +def rustfmtcheck(args=None): + """ Performs a format check on the Rust test files """ + if not checkRustComponent('rustfmt'): + mx.warn("'rustfmt' is not available") + return + for f in rustfmtCheckPaths: + checkFiles(f, checkRustFile, ['rs']) + +def checkFiles(targetDir, fileChecker, exts): error = False for path, _, files in os.walk(targetDir): for f in files: - if f.endswith('.c') or f.endswith('.cpp') or f.endswith('.h') or f.endswith('.hpp'): - if not checkCFile(path + '/' + f): + if f.endswith(tuple(exts)): + if not fileChecker(path + '/' + f): error = True if error: mx.log_error("found formatting errors!") @@ -247,6 +262,22 @@ def checkCFile(targetFile): return False return True +def checkRustFile(targetFile): + """ Checks the formatting of a Rust file and returns True if the formatting is okay """ + if not checkRustComponent('rustfmt'): + exit("Unable to find 'rustfmt' executable") + returncode_check = mx.run(['rustfmt', '--check', targetFile], nonZeroIsFatal=False) + if returncode_check == 1: + # formatted code differs from existing code or error occured; try to modify the file to the right format + returncode_replace = mx.run(['rustfmt', targetFile], nonZeroIsFatal=False) + if returncode_replace == 0: + mx.log('modified formatting in {0}'.format(targetFile)) + return False + elif returncode_check == 0: + return True + mx.log_error('encountered parsing errors or operational errors when trying to format {0}'.format(targetFile)) + return False + # platform dependent def pullLLVMBinaries(args=None): """downloads the LLVM binaries""" @@ -296,14 +327,14 @@ def dragonEggGPP(args=None): executeCommand = [getGPP(), "-fplugin=" + dragonEggPath(), '-fplugin-arg-dragonegg-emit-ir'] return mx.run(executeCommand + args) -def checkRust(): - """checks if a Rust installation is available; may try to install the active toolchain if it is missing""" - if os.environ.get('SULONG_USE_RUSTC', 'true') == 'false' or which('rustc') is None: +def checkRustComponent(componentName): + """checks if a Rust component is available; may try to install the active toolchain if it is missing""" + if (componentName == 'rustc' and os.environ.get('SULONG_USE_RUSTC', 'true') == 'false') or which(componentName) is None: return False - rustc = subprocess.Popen(['rustc', '--version'], stdout=subprocess.PIPE) - rustc.communicate() - return rustc.returncode == 0 + component = subprocess.Popen([componentName, '--version'], stdout=subprocess.PIPE) + component.communicate() + return component.returncode == 0 def which(program, searchPath=None): def is_exe(fpath): @@ -640,7 +671,7 @@ def findGCCProgram(gccProgram, optional=False): def findRustLibrary(name, on_failure=exit): """looks up the path to the given Rust library for the active toolchain; may try to install the active toolchain if it is missing; exits by default if installation fails""" - if not checkRust(): + if not checkRustComponent('rustc'): on_failure('Rust is not available') return None diff --git a/mx.sulong/mx_testsuites.py b/mx.sulong/mx_testsuites.py index 190f671f1..2570978d8 100644 --- a/mx.sulong/mx_testsuites.py +++ b/mx.sulong/mx_testsuites.py @@ -301,7 +301,7 @@ def __init__(self, isFulfilled): def isFulfilled(self): return self._isFulfilled() -Dependency.RUST = Dependency(lambda: mx_sulong.checkRust()) # pylint: disable=W0108 +Dependency.RUST = Dependency(lambda: mx_sulong.checkRustComponent('rustc')) # pylint: disable=W0108 Dependency.DRAGONEGG = Dependency(lambda: mx_sulong.dragonEggPath() is not None and os.path.exists(mx_sulong.dragonEggPath()) and mx_sulong.getGCC(optional=True) is not None) class SulongTestSuite(mx.NativeProject): diff --git a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs index b51564175..25f7f62f5 100644 --- a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs +++ b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs @@ -1,3 +1,3 @@ -fn main(){ - std::process::exit(42); +fn main() { + std::process::exit(42); } diff --git a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs index f116527e2..47ad8c634 100644 --- a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs +++ b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs @@ -1,3 +1,3 @@ -fn main(){ - println!("Hello World!"); +fn main() { + println!("Hello World!"); }