From 5862542dedd5aca9bbdcba19c5f8cd895591005d Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 13 Jan 2019 00:19:20 +0100 Subject: Add AST/HIR for type args in path segments --- crates/ra_hir/src/path.rs | 68 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir/src/path.rs') diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index 7b0ce3b61..c3d14c689 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs @@ -1,11 +1,35 @@ +use std::sync::Arc; + use ra_syntax::{ast, AstNode}; -use crate::{Name, AsName}; +use crate::{Name, AsName, type_ref::TypeRef}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { pub kind: PathKind, - pub segments: Vec, + pub segments: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PathSegment { + pub name: Name, + pub args_and_bindings: Option>, +} + +/// Generic arguments to a path segment (e.g. the `i32` in `Option`). This +/// can (in the future) also include bindings of associated types, like in +/// `Iterator`. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct GenericArgs { + pub args: Vec, + // someday also bindings +} + +/// A single generic argument. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum GenericArg { + Type(TypeRef), + // or lifetime... } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -34,7 +58,17 @@ impl Path { loop { let segment = path.segment()?; match segment.kind()? { - ast::PathSegmentKind::Name(name) => segments.push(name.as_name()), + ast::PathSegmentKind::Name(name) => { + let args = segment + .type_arg_list() + .and_then(GenericArgs::from_ast) + .map(Arc::new); + let segment = PathSegment { + name: name.as_name(), + args_and_bindings: args, + }; + segments.push(segment); + } ast::PathSegmentKind::CrateKw => { kind = PathKind::Crate; break; @@ -88,7 +122,23 @@ impl Path { if self.kind != PathKind::Plain || self.segments.len() > 1 { return None; } - self.segments.first() + self.segments.first().map(|s| &s.name) + } +} + +impl GenericArgs { + fn from_ast(node: &ast::TypeArgList) -> Option { + let mut args = Vec::new(); + for type_arg in node.type_args() { + let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); + args.push(GenericArg::Type(type_ref)); + } + // lifetimes and assoc type args ignored for now + if args.len() > 0 { + Some(GenericArgs { args }) + } else { + None + } } } @@ -96,7 +146,10 @@ impl From for Path { fn from(name: Name) -> Path { Path { kind: PathKind::Plain, - segments: vec![name], + segments: vec![PathSegment { + name, + args_and_bindings: None, + }], } } } @@ -160,7 +213,10 @@ fn convert_path(prefix: Option, path: &ast::Path) -> Option { kind: PathKind::Plain, segments: Vec::with_capacity(1), }); - res.segments.push(name.as_name()); + res.segments.push(PathSegment { + name: name.as_name(), + args_and_bindings: None, // no type args in use + }); res } ast::PathSegmentKind::CrateKw => { -- cgit v1.2.3