diff --git a/Cargo.lock b/Cargo.lock index a0ab2f67..18b3e897 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,52 +13,68 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", ] +[[package]] +name = "assert_cmd" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + [[package]] name = "assert_matches" version = "1.5.0" @@ -67,9 +83,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bitflags" @@ -93,6 +109,17 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -141,15 +168,15 @@ checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -175,15 +202,15 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "dactyl" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94055d86faa2715e63740352efcb018b05fb758a9657d0fc73eaf499d2d62321" +checksum = "5cf28ee1e8e5bb53ebea93776d80b71465d6c670a7221672557974e7935784e8" [[package]] name = "diff" @@ -191,6 +218,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "dirs" version = "5.0.1" @@ -212,6 +245,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "dunce" version = "1.0.4" @@ -220,9 +259,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "enum-map" @@ -275,9 +314,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -285,9 +324,18 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "float-cmp" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] [[package]] name = "fnv" @@ -306,9 +354,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -323,9 +371,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" @@ -365,11 +413,17 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -382,9 +436,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" @@ -398,9 +452,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" @@ -449,6 +503,21 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -466,9 +535,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -499,6 +568,36 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "268ad82d92622fb0a049ff14b01089b0f1bcd5c507fab44724394d328417348a" +[[package]] +name = "predicates" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +dependencies = [ + "anstyle", + "difflib", + "float-cmp", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "pretty_assertions" version = "1.4.0" @@ -511,9 +610,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] @@ -611,15 +710,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scopeguard" @@ -629,18 +728,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.199" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", @@ -649,9 +748,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -671,9 +770,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -724,9 +823,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -745,20 +844,26 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", @@ -782,9 +887,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" dependencies = [ "serde", "serde_spanned", @@ -794,18 +899,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.12" +version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" +checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" dependencies = [ "indexmap", "serde", @@ -863,6 +968,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" name = "vhdl_lang" version = "0.80.0" dependencies = [ + "assert_cmd", "assert_matches", "brunch", "clap", @@ -875,6 +981,7 @@ dependencies = [ "pad", "parking_lot", "pinned_vec", + "predicates", "pretty_assertions", "rayon", "strum", @@ -909,6 +1016,15 @@ dependencies = [ "vhdl_lang", ] +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1056,9 +1172,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b9415ee827af173ebb3f15f9083df5a122eb93572ec28741fb153356ea2578" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" dependencies = [ "memchr", ] diff --git a/vhdl_lang/Cargo.toml b/vhdl_lang/Cargo.toml index ecf97380..65036415 100644 --- a/vhdl_lang/Cargo.toml +++ b/vhdl_lang/Cargo.toml @@ -35,6 +35,8 @@ tempfile = "3" pretty_assertions = "1" assert_matches = "1" brunch = "0" +assert_cmd = "2.0.14" +predicates = "3.1.0" [[bench]] name = "benchmark" diff --git a/vhdl_lang/src/config.rs b/vhdl_lang/src/config.rs index 34819575..be0be812 100644 --- a/vhdl_lang/src/config.rs +++ b/vhdl_lang/src/config.rs @@ -253,7 +253,15 @@ impl Config { } /// Load configuration file from installation folder - fn load_installed_config(&mut self, messages: &mut dyn MessageHandler) { + fn load_installed_config( + &mut self, + messages: &mut dyn MessageHandler, + location: Option, + ) { + if let Some(location) = location { + self.load_config(&PathBuf::from(location), "Installation", messages); + return; + } let search_paths = [ "../vhdl_libraries", "../../vhdl_libraries", @@ -325,8 +333,17 @@ impl Config { } /// Load all external configuration - pub fn load_external_config(&mut self, messages: &mut dyn MessageHandler) { - self.load_installed_config(messages); + /// If the `standard_libraries_path` is given, it must point to a valid + /// `vhdl_ls.toml` file, which will be used as source for the standard libraries + /// i.e., `std` or `ieee`. + /// If this path is `None`, a set of standard search paths will be queried for the location + /// of this file. + pub fn load_external_config( + &mut self, + messages: &mut dyn MessageHandler, + standard_libraries_path: Option, + ) { + self.load_installed_config(messages, standard_libraries_path); self.load_home_config(messages); self.load_env_config("VHDL_LS_CONFIG", messages); } diff --git a/vhdl_lang/src/main.rs b/vhdl_lang/src/main.rs index 8d951e85..6364f3e6 100644 --- a/vhdl_lang/src/main.rs +++ b/vhdl_lang/src/main.rs @@ -5,43 +5,26 @@ // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com use clap::Parser; +use itertools::Itertools; use std::path::Path; -use std::time::SystemTime; -use vhdl_lang::{Config, Diagnostic, MessagePrinter, NullMessages, Project, Severity, SeverityMap}; +use vhdl_lang::{Config, Diagnostic, MessagePrinter, Project, Severity, SeverityMap}; /// Run vhdl analysis #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct Args { - /// The number of threads to use. By default the maximum is selected based on process cores + /// The number of threads to use. By default, the maximum is selected based on process cores #[arg(short = 'p', long)] num_threads: Option, - /// Prints the number of files processed and the execution time - #[arg(long, default_value_t = false)] - perf: bool, - - /// Run repeatedly to get a reliable benchmark result - #[arg(long, default_value_t = false)] - bench: bool, - - /// Hide hint diagnostics - #[arg(long, default_value_t = false)] - no_hint: bool, + /// Path to the config file for the VHDL standard libraries (i.e., IEEE std_logic_1164). + /// If omitted, will search for these libraries in a set of standard paths + #[arg(short = 'l', long)] + libraries: Option, /// Config file in TOML format containing libraries and settings #[arg(short, long)] config: String, - - /// Dump items that are not resolved into an unique reference - /// This is used for development to test where the language server is blind - #[arg(long)] - dump_unresolved: bool, - - /// Count items that are not resolved into an unique reference - /// This is used for development to test where the language server is blind - #[arg(long)] - count_unresolved: bool, } fn main() { @@ -53,77 +36,36 @@ fn main() { let mut config = Config::default(); let mut msg_printer = MessagePrinter::default(); - config.load_external_config(&mut msg_printer); + config.load_external_config(&mut msg_printer, args.libraries.clone()); config.append( &Config::read_file_path(Path::new(&args.config)).expect("Failed to read config file"), &mut msg_printer, ); - let start = SystemTime::now(); - - let iterations = if args.bench { - let iterations = 10; - println!("Running {iterations} iterations for benchmarking"); - for _ in 0..(iterations - 1) { - let mut project = Project::from_config(config.clone(), &mut NullMessages); - project.analyse(); - } - iterations - } else { - 1 - }; - let severity_map = *config.severities(); let mut project = Project::from_config(config, &mut msg_printer); - let mut diagnostics = project.analyse(); - let duration = start.elapsed().unwrap() / iterations; - - if args.no_hint { - diagnostics.retain(|diag| severity_map[diag.code] != Some(Severity::Hint)); - } + project.enable_unused_declaration_detection(); + let diagnostics = project.analyse(); show_diagnostics(&diagnostics, &severity_map); - if args.perf || args.bench { - let mut num_files = 0; - let mut num_lines = 0; - for source_file in project.files() { - num_files += 1; - num_lines += source_file.num_lines(); - } - let duration_per_line = duration.checked_div(num_lines as u32).unwrap(); - - println!("Analyzed {num_files} files with {num_lines} lines of code"); - println!( - "Total time to run was {} ms with an average of {} ns per line", - duration.as_millis(), - duration_per_line.as_nanos() - ); - } - - if args.dump_unresolved || args.count_unresolved { - let (total, unresolved) = project.find_all_unresolved(); - - if args.dump_unresolved { - for pos in unresolved.iter() { - println!("{}", pos.show("Unresolved")); - } - } - - if args.count_unresolved { - println!("{} out of {} positions unresolved", unresolved.len(), total); - } + if diagnostics + .iter() + .any(|diag| severity_map[diag.code].is_some_and(|severity| severity == Severity::Error)) + { + std::process::exit(1); + } else { + std::process::exit(0); } - - // Exit without running Drop on entire allocated AST - std::process::exit(0); } fn show_diagnostics(diagnostics: &[Diagnostic], severity_map: &SeverityMap) { - for diagnostic in diagnostics { - if let Some(str) = diagnostic.show(severity_map) { - println!("{str}"); - } + let diagnostics = diagnostics + .iter() + .filter_map(|diag| diag.show(severity_map)) + .collect_vec(); + for str in &diagnostics { + println!("{str}"); } if !diagnostics.is_empty() { diff --git a/vhdl_lang/tests/integration_tests.rs b/vhdl_lang/tests/integration_tests.rs new file mode 100644 index 00000000..9d6b0d05 --- /dev/null +++ b/vhdl_lang/tests/integration_tests.rs @@ -0,0 +1,60 @@ +use assert_cmd::prelude::*; +use itertools::Itertools; +use predicates::prelude::*; +use std::error::Error; +use std::path::PathBuf; +use std::process::Command; +use vhdl_lang::{Config, MessagePrinter, Project, Severity}; + +#[test] +pub fn parses_example_project_without_errors() { + let mut config = Config::default(); + let mut msg_printer = MessagePrinter::default(); + + let mut vhdl_libraries_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + // Load the VHDL standard libraries + vhdl_libraries_path.push("../vhdl_libraries/vhdl_ls.toml"); + config.append( + &Config::read_file_path(&vhdl_libraries_path).expect("Failed to read config file"), + &mut msg_printer, + ); + + // Load the configuration from the example project + let mut config_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + config_path.push("../example_project/vhdl_ls.toml"); + config.append( + &Config::read_file_path(&config_path).expect("Failed to read config file"), + &mut msg_printer, + ); + + let severity_map = *config.severities(); + let mut project = Project::from_config(config, &mut msg_printer); + project.enable_unused_declaration_detection(); + + let diagnostics = project.analyse(); + let diagnostics_with_errors = diagnostics + .iter() + .filter(|diag| severity_map[diag.code] == Some(Severity::Error)) + .collect_vec(); + if !diagnostics_with_errors.is_empty() { + for diagnostic in diagnostics_with_errors { + println!("{}", diagnostic.show(&severity_map).unwrap()) + } + panic!("Found diagnostics with severity error in the example project"); + } +} + +#[test] +fn unused_function_gets_detected() -> Result<(), Box> { + let mut cmd = Command::cargo_bin("vhdl_lang")?; + + cmd.arg("--config") + .arg("tests/unused_declarations/vhdl_ls.toml") + .arg("--libraries") + .arg("../vhdl_libraries/vhdl_ls.toml"); + cmd.assert().failure().stdout(predicate::str::contains( + "error: Unused declaration of port 'baz' : inout", + )); + + Ok(()) +} diff --git a/vhdl_lang/tests/unused_declarations/my_entity.vhd b/vhdl_lang/tests/unused_declarations/my_entity.vhd new file mode 100644 index 00000000..905393f1 --- /dev/null +++ b/vhdl_lang/tests/unused_declarations/my_entity.vhd @@ -0,0 +1,15 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity my_ent is + port ( + foo : in std_logic; + bar : out std_logic; + baz : inout std_logic + ); +end my_ent; + +architecture arch of my_ent is +begin + bar <= foo; +end architecture arch; diff --git a/vhdl_lang/tests/unused_declarations/vhdl_ls.toml b/vhdl_lang/tests/unused_declarations/vhdl_ls.toml new file mode 100644 index 00000000..907633f6 --- /dev/null +++ b/vhdl_lang/tests/unused_declarations/vhdl_ls.toml @@ -0,0 +1,6 @@ +[libraries] + +my_library.files = ["my_entity.vhd"] + +[lint] +unused = "error" diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index ee999667..38877cf8 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -116,7 +116,7 @@ impl VHDLServer { let mut config = Config::default(); if self.use_external_config { - config.load_external_config(&mut self.message_filter()); + config.load_external_config(&mut self.message_filter(), None); } match self.load_root_uri_config() {