commit 1803c26d00a8c55dbd14aeb87a17dfcd8a38cb6a
parent a6a8cee2fd9706dbe479cb55a08011cc78ec0ab9
Author: Lou Woell <lou.woell@posteo.de>
Date: Tue, 16 Sep 2025 01:01:46 +0200
[locate] handle identifiers with trailing ::
Diffstat:
3 files changed, 72 insertions(+), 19 deletions(-)
diff --git a/cmd/harehelper/+test/locate_test.ha b/cmd/harehelper/+test/locate_test.ha
@@ -1,8 +1,11 @@
+use bufio;
use dirs;
use fmt;
+use hare::ast;
use hare::lex;
use hare::module;
use hare::parse;
+use memio;
use os;
use strings;
@@ -21,9 +24,29 @@ fn loc_test_fn (in: str, out: lex::location) void = {
tags = ["linux", "test"],
};
- const id = parse::identstr(in)!;
+ let buf = memio::fixed(strings::toutf8(in));
+ let sc = bufio::newscanner(&buf);
+ defer bufio::finish(&sc);
+ let lexer = lex::init(&sc, "<string>");
- match(locate_symbol(&ctx, id)) {
+ let (id, trailing) = match (parse::ident_trailing(&lexer)) {
+ case parse::error =>
+ return void;
+ case let r: (ast::ident, bool) =>
+ yield r;
+ };
+ defer ast::ident_free(id);
+
+ let loc: (lex::location | void) = void;
+ if (!trailing) {
+ loc = locate_symbol(&ctx, id);
+ };
+
+ if(loc is void){
+ loc = locate_module(&ctx, id);
+ };
+
+ match(loc) {
case void => abort();
case let l: lex::location =>
fmt::errorfln("path: {}, expected: {}", l.path, out.path)!;
@@ -47,7 +70,7 @@ fn loc_test_fn (in: str, out: lex::location) void = {
@test fn locate_local_func() void = {
loc_test_fn("cmd::harehelper::loc_test_fn", lex::location {
path = "locate_test.ha",
- line = 10,
+ line = 13,
col = 20,
...
});
@@ -56,7 +79,7 @@ fn loc_test_fn (in: str, out: lex::location) void = {
@test fn locate_global_multiple1 () void = {
loc_test_fn("cmd::harehelper::s", lex::location {
path = "locate_test.ha",
- line = 9,
+ line = 12,
col = 18,
...
});
@@ -65,7 +88,7 @@ fn loc_test_fn (in: str, out: lex::location) void = {
@test fn locate_global_multiple2 () void = {
loc_test_fn("cmd::harehelper::d", lex::location {
path = "locate_test.ha",
- line = 9,
+ line = 12,
col = 18,
...
});
@@ -74,7 +97,7 @@ fn loc_test_fn (in: str, out: lex::location) void = {
@test fn locate_const_multiple1 () void = {
loc_test_fn("cmd::harehelper::q", lex::location {
path = "locate_test.ha",
- line = 7,
+ line = 10,
col = 13,
...
});
@@ -83,7 +106,7 @@ fn loc_test_fn (in: str, out: lex::location) void = {
@test fn locate_const_multiple2 () void = {
loc_test_fn("cmd::harehelper::w", lex::location {
path = "locate_test.ha",
- line = 7,
+ line = 10,
col = 13,
...
});
@@ -97,3 +120,12 @@ fn loc_test_fn (in: str, out: lex::location) void = {
...
});
};
+
+@test fn locate_module_trailing () void = {
+ loc_test_fn("os::", lex::location {
+ path = "os",
+ line = 0,
+ col = 0,
+ ...
+ });
+};
diff --git a/cmd/harehelper/locate.ha b/cmd/harehelper/locate.ha
@@ -12,12 +12,14 @@
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <https://www.gnu.org/licenses/>.
+use bufio;
use fmt;
use getopt::{command};
use hare::ast;
use hare::lex;
use hare::module;
use hare::parse;
+use memio;
use os;
use path;
use strings;
@@ -26,32 +28,45 @@ fn locate (cmd: command, ctx: *module::context) void = {
if(len(cmd.args) == 0) fmt::fatal("Expected Argument");
- let id = match (parse::identstr(cmd.args[0])) {
+ let in = memio::fixed(strings::toutf8(cmd.args[0]));
+ let sc = bufio::newscanner(&in);
+ defer bufio::finish(&sc);
+ let lexer = lex::init(&sc, "<string>");
+
+ let (id, trailing) = match (parse::ident_trailing(&lexer)) {
case parse::error =>
return void;
- case let id: ast::ident =>
- yield id;
+ case let r: (ast::ident, bool) =>
+ yield r;
};
defer ast::ident_free(id);
- match (locate_symbol(ctx, id)) {
- case void =>
- return void;
+ let loc: (lex::location | void) = void;
+ if (!trailing) {
+ loc = locate_symbol(ctx, id);
+ };
+
+ if(loc is void){
+ loc = locate_module(ctx, id);
+ };
+
+
+ match (loc) {
+ case void=> void;
case let d: lex::location =>
fmt::printfln("{}:{}:{}", d.path, d.line, d.col)!;
free(d.path);
};
};
-fn locate_symbol (
+fn locate_module (
ctx: *module::context,
id: ast::ident
) (lex::location | void) = {
-
- // Check if id is a module
match (module::find(ctx, id)) {
case let e: module::error =>
module::finish_error(e);
+ return void;
case let r: (str, module::srcset) =>
defer module::finish_srcset(&r.1);
return lex::location {
@@ -61,8 +76,14 @@ fn locate_symbol (
off = 0,
};
};
+};
+
+
+fn locate_symbol (
+ ctx: *module::context,
+ id: ast::ident
+) (lex::location | void) = {
- // else: treat id as having the form namespace::symbol.
let ns: module::location = ident_ns(id);
// if no namespace prefix is present look for a declaration in the cwd.
if (len(id) <= 1) {
diff --git a/haredoc.el b/haredoc.el
@@ -132,7 +132,7 @@
"Run haredoc with the current word under the cursor and display
the results in a new buffer."
(interactive)
- (let* ((id (string-trim-right (or sign (haredoc/read-module)) "::"))
+ (let* ((id (or sign (haredoc/read-module)))
(components (string-split id "::" t))
(location (haredoc/get-location id))
(location (string-split location ":" t))
@@ -141,7 +141,7 @@ the results in a new buffer."
(string-join (butlast components) "::")
(car components)))
(current-ns (if (f-directory? path)
- id
+ (string-trim-right id "::")
parent-ns)))
(when haredoc-stack-item
(push haredoc-stack-item haredoc-backward-stack)