From 5d54aa678153d0af0edc8b4dd2d74709d10ca66c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 23 May 2019 20:18:47 +0300 Subject: add union to code_model --- crates/ra_hir/src/adt.rs | 7 ++-- crates/ra_hir/src/code_model_api.rs | 38 ++++++++++++++++++++++ crates/ra_hir/src/generics.rs | 13 ++++++-- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/nameres/collector.rs | 6 +++- crates/ra_hir/src/nameres/raw.rs | 19 ++++++----- crates/ra_hir/src/ty.rs | 1 + crates/ra_hir/src/ty/infer.rs | 21 +++++++----- crates/ra_hir/src/ty/lower.rs | 10 ++++-- .../src/completion/complete_struct_literal.rs | 1 + crates/ra_ide_api/src/completion/presentation.rs | 1 + crates/ra_ide_api/src/display/navigation_target.rs | 8 +++++ crates/ra_ide_api/src/syntax_highlighting.rs | 1 + 13 files changed, 102 insertions(+), 26 deletions(-) diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index e027eedd9..5e5905f15 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -10,7 +10,7 @@ use ra_syntax::{ }; use crate::{ - Name, AsName, Struct, Enum, EnumVariant, Crate, + Name, AsName, Struct, Union, Enum, EnumVariant, Crate, HirDatabase, HirFileId, StructField, FieldSource, type_ref::TypeRef, DefDatabase, }; @@ -18,14 +18,16 @@ use crate::{ #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum AdtDef { Struct(Struct), + Union(Union), Enum(Enum), } -impl_froms!(AdtDef: Struct, Enum); +impl_froms!(AdtDef: Struct, Union, Enum); impl AdtDef { pub(crate) fn krate(self, db: &impl HirDatabase) -> Option { match self { AdtDef::Struct(s) => s.module(db), + AdtDef::Union(s) => s.module(db), AdtDef::Enum(e) => e.module(db), } .krate(db) @@ -38,6 +40,7 @@ impl Struct { } } +/// Note that we use `StructData` for unions as well! #[derive(Debug, Clone, PartialEq, Eq)] pub struct StructData { pub(crate) name: Option, diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 0c4a80bfa..970b78412 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -71,6 +71,7 @@ pub enum ModuleDef { Module(Module), Function(Function), Struct(Struct), + Union(Union), Enum(Enum), // Can't be directly declared, but can be imported. EnumVariant(EnumVariant), @@ -83,6 +84,7 @@ impl_froms!( ModuleDef: Module, Function, Struct, + Union, Enum, EnumVariant, Const, @@ -325,6 +327,42 @@ impl Docs for Struct { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Union { + pub(crate) id: StructId, +} + +impl Union { + pub fn source(&self, db: &impl DefDatabase) -> (HirFileId, TreeArc) { + self.id.source(db) + } + + pub fn name(&self, db: &impl HirDatabase) -> Option { + db.struct_data(Struct { id: self.id }).name.clone() + } + + pub fn module(&self, db: &impl HirDatabase) -> Module { + self.id.module(db) + } + + // FIXME move to a more general type + /// Builds a resolver for type references inside this union. + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { + // take the outer scope... + let r = self.module(db).resolver(db); + // ...and add generic params, if present + let p = self.generic_params(db); + let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; + r + } +} + +impl Docs for Union { + fn docs(&self, db: &impl HirDatabase) -> Option { + docs_from_ast(&*self.source(db).1) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Enum { pub(crate) id: EnumId, diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 79a7fa23a..8effbbe35 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -9,7 +9,7 @@ use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner, DefaultT use crate::{ db::{ HirDatabase, DefDatabase}, - Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef + Name, AsName, Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef }; /// Data about a generic parameter (to a function, struct, impl, ...). @@ -42,12 +42,13 @@ pub struct WherePredicate { pub enum GenericDef { Function(Function), Struct(Struct), + Union(Union), Enum(Enum), Trait(Trait), TypeAlias(TypeAlias), ImplBlock(ImplBlock), } -impl_froms!(GenericDef: Function, Struct, Enum, Trait, TypeAlias, ImplBlock); +impl_froms!(GenericDef: Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock); impl GenericParams { pub(crate) fn generic_params_query( @@ -58,7 +59,10 @@ impl GenericParams { let parent = match def { GenericDef::Function(it) => it.container(db).map(GenericDef::from), GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), - GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, + GenericDef::Struct(_) + | GenericDef::Union(_) + | GenericDef::Enum(_) + | GenericDef::Trait(_) => None, GenericDef::ImplBlock(_) => None, }; generics.parent_params = parent.map(|p| db.generic_params(p)); @@ -66,6 +70,7 @@ impl GenericParams { match def { GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), + GenericDef::Union(it) => generics.fill(&*it.source(db).1, start), GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), GenericDef::Trait(it) => { // traits get the Self type as an implicit first type parameter @@ -171,6 +176,7 @@ impl GenericDef { match self { GenericDef::Function(inner) => inner.resolver(db), GenericDef::Struct(inner) => inner.resolver(db), + GenericDef::Union(inner) => inner.resolver(db), GenericDef::Enum(inner) => inner.resolver(db), GenericDef::Trait(inner) => inner.resolver(db), GenericDef::TypeAlias(inner) => inner.resolver(db), @@ -192,6 +198,7 @@ impl From for GenericDef { fn from(adt: crate::adt::AdtDef) -> Self { match adt { AdtDef::Struct(s) => s.into(), + AdtDef::Union(u) => u.into(), AdtDef::Enum(e) => e.into(), } } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 0c6d7c2b7..0135644db 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -77,7 +77,7 @@ pub use self::code_model_api::{ Crate, CrateDependency, DefWithBody, Module, ModuleDef, ModuleSource, - Struct, Enum, EnumVariant, + Struct, Union, Enum, EnumVariant, Function, FnSignature, StructField, FieldSource, Static, Const, ConstSignature, diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs index c615d80c3..621236551 100644 --- a/crates/ra_hir/src/nameres/collector.rs +++ b/crates/ra_hir/src/nameres/collector.rs @@ -6,7 +6,7 @@ use ra_db::FileId; use ra_syntax::ast; use crate::{ - Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, + Function, Module, Struct, Union, Enum, Const, Static, Trait, TypeAlias, DefDatabase, HirFileId, Name, Path, KnownName, nameres::{ @@ -495,6 +495,10 @@ where let s = def!(Struct, ast_id); PerNs::both(s, s) } + raw::DefKind::Union(ast_id) => { + let s = def!(Union, ast_id); + PerNs::both(s, s) + } raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)), raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)), raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)), diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs index bd32b264b..1b4dcbb7a 100644 --- a/crates/ra_hir/src/nameres/raw.rs +++ b/crates/ra_hir/src/nameres/raw.rs @@ -1,7 +1,4 @@ -use std::{ - sync::Arc, - ops::Index, -}; +use std::{sync::Arc, ops::Index}; use test_utils::tested_by; use ra_arena::{Arena, impl_arena_id, RawId, map::ArenaMap}; @@ -10,10 +7,7 @@ use ra_syntax::{ ast::{self, NameOwner, AttrsOwner}, }; -use crate::{ - DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, - AstIdMap, FileAstId, Either, -}; +use crate::{DefDatabase, Name, AsName, Path, HirFileId, ModuleSource, AstIdMap, FileAstId, Either}; /// `RawItems` is a set of top-level items in a file (except for impls). /// @@ -161,6 +155,7 @@ pub(super) struct DefData { pub(super) enum DefKind { Function(FileAstId), Struct(FileAstId), + Union(FileAstId), Enum(FileAstId), Const(FileAstId), Static(FileAstId), @@ -215,7 +210,13 @@ impl RawItemsCollector { return; } ast::ModuleItemKind::StructDef(it) => { - (DefKind::Struct(self.source_ast_id_map.ast_id(it)), it.name()) + let id = self.source_ast_id_map.ast_id(it); + let name = it.name(); + if it.is_union() { + (DefKind::Union(id), name) + } else { + (DefKind::Struct(id), name) + } } ast::ModuleItemKind::EnumDef(it) => { (DefKind::Enum(self.source_ast_id_map.ast_id(it)), it.name()) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 3679a2242..76d34c12b 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -536,6 +536,7 @@ impl HirDisplay for ApplicationTy { TypeCtor::Adt(def_id) => { let name = match def_id { AdtDef::Struct(s) => s.name(f.db), + AdtDef::Union(u) => u.name(f.db), AdtDef::Enum(e) => e.name(f.db), } .unwrap_or_else(Name::missing); diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index a48272981..7d8250292 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -27,13 +27,13 @@ use ra_prof::profile; use test_utils::tested_by; use crate::{ - Function, StructField, Path, Name, - FnSignature, AdtDef,ConstSignature, - HirDatabase, - DefWithBody, - ImplItem, + Function, StructField, Path, Name, FnSignature, AdtDef, ConstSignature, HirDatabase, + DefWithBody, ImplItem, type_ref::{TypeRef, Mutability}, - expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat,Array, self}, + expr::{ + Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, + FieldPat, Array, self, + }, generics::{GenericParams, HasGenericParams}, path::{GenericArgs, GenericArg}, ModuleDef, @@ -644,7 +644,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let ty = self.insert_type_vars(ty.apply_substs(substs)); (ty, Some(var.into())) } - TypableDef::TypeAlias(_) + TypableDef::Union(_) + | TypableDef::TypeAlias(_) | TypableDef::Function(_) | TypableDef::Enum(_) | TypableDef::Const(_) @@ -1407,7 +1408,11 @@ impl Expectation { } mod diagnostics { - use crate::{expr::ExprId, diagnostics::{DiagnosticSink, NoSuchField}, HirDatabase, Function}; + use crate::{ + expr::ExprId, + diagnostics::{DiagnosticSink, NoSuchField}, + HirDatabase, Function, +}; #[derive(Debug, PartialEq, Eq, Clone)] pub(super) enum InferenceDiagnostic { diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index a1a2d0f6b..7defa7a9b 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use std::iter; use crate::{ - Function, Struct, StructField, Enum, EnumVariant, Path, ModuleDef, TypeAlias, Const, Static, + Function, Struct, Union, StructField, Enum, EnumVariant, Path, ModuleDef, TypeAlias, Const, Static, HirDatabase, type_ref::TypeRef, name::KnownName, @@ -124,6 +124,7 @@ impl Ty { let def_generic: Option = match resolved { TypableDef::Function(func) => Some(func.into()), TypableDef::Struct(s) => Some(s.into()), + TypableDef::Union(u) => Some(u.into()), TypableDef::Enum(e) => Some(e.into()), TypableDef::EnumVariant(var) => Some(var.parent_enum(db).into()), TypableDef::TypeAlias(t) => Some(t.into()), @@ -144,6 +145,7 @@ impl Ty { let segment = match resolved { TypableDef::Function(_) | TypableDef::Struct(_) + | TypableDef::Union(_) | TypableDef::Enum(_) | TypableDef::Const(_) | TypableDef::Static(_) @@ -293,12 +295,14 @@ pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s), (TypableDef::Enum(e), Namespace::Types) => type_for_adt(db, e), (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), + (TypableDef::Union(u), Namespace::Types) => type_for_adt(db, u), (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t), (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c), (TypableDef::Static(c), Namespace::Values) => type_for_static(db, c), // 'error' cases: (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, + (TypableDef::Union(_), Namespace::Values) => Ty::Unknown, (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown, (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown, (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown, @@ -467,19 +471,21 @@ fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { pub enum TypableDef { Function(Function), Struct(Struct), + Union(Union), Enum(Enum), EnumVariant(EnumVariant), TypeAlias(TypeAlias), Const(Const), Static(Static), } -impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant, TypeAlias, Const, Static); +impl_froms!(TypableDef: Function, Struct, Union, Enum, EnumVariant, TypeAlias, Const, Static); impl From for Option { fn from(def: ModuleDef) -> Option { let res = match def { ModuleDef::Function(f) => f.into(), ModuleDef::Struct(s) => s.into(), + ModuleDef::Union(u) => u.into(), ModuleDef::Enum(e) => e.into(), ModuleDef::EnumVariant(v) => v.into(), ModuleDef::TypeAlias(t) => t.into(), diff --git a/crates/ra_ide_api/src/completion/complete_struct_literal.rs b/crates/ra_ide_api/src/completion/complete_struct_literal.rs index 48fbf67f7..a00c1b60b 100644 --- a/crates/ra_ide_api/src/completion/complete_struct_literal.rs +++ b/crates/ra_ide_api/src/completion/complete_struct_literal.rs @@ -20,6 +20,7 @@ pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionCon } // FIXME unions + AdtDef::Union(_) => (), AdtDef::Enum(_) => (), }; } diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index 9aa346688..064d379a4 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs @@ -63,6 +63,7 @@ impl Completions { return self.add_function_with_name(ctx, Some(local_name), *func); } Resolution::Def(Struct(it)) => (CompletionItemKind::Struct, it.docs(ctx.db)), + Resolution::Def(Union(it)) => (CompletionItemKind::Struct, it.docs(ctx.db)), Resolution::Def(Enum(it)) => (CompletionItemKind::Enum, it.docs(ctx.db)), Resolution::Def(EnumVariant(it)) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), Resolution::Def(Const(it)) => (CompletionItemKind::Const, it.docs(ctx.db)), diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index 1c694cbc9..7f81483f7 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs @@ -154,6 +154,10 @@ impl NavigationTarget { let (file_id, node) = s.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) } + hir::AdtDef::Union(s) => { + let (file_id, node) = s.source(db); + NavigationTarget::from_named(file_id.original_file(db), &*node) + } hir::AdtDef::Enum(s) => { let (file_id, node) = s.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) @@ -169,6 +173,10 @@ impl NavigationTarget { let (file_id, node) = s.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) } + hir::ModuleDef::Union(s) => { + let (file_id, node) = s.source(db); + NavigationTarget::from_named(file_id.original_file(db), &*node) + } hir::ModuleDef::Const(s) => { let (file_id, node) = s.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 89f20260f..77c9ae3b1 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -57,6 +57,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec "module", Some(Def(ModuleDef::Function(_))) => "function", Some(Def(ModuleDef::Struct(_))) => "type", + Some(Def(ModuleDef::Union(_))) => "type", Some(Def(ModuleDef::Enum(_))) => "type", Some(Def(ModuleDef::EnumVariant(_))) => "constant", Some(Def(ModuleDef::Const(_))) => "constant", -- cgit v1.2.3