add union to code_model

This commit is contained in:
Aleksey Kladov 2019-05-23 20:18:47 +03:00
parent eef24bddc9
commit 5d54aa6781
13 changed files with 102 additions and 26 deletions

View File

@ -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<Crate> {
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<Name>,

View File

@ -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<ast::StructDef>) {
self.id.source(db)
}
pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
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<Documentation> {
docs_from_ast(&*self.source(db).1)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Enum {
pub(crate) id: EnumId,

View File

@ -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<crate::adt::AdtDef> 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(),
}
}

View File

@ -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,

View File

@ -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)),

View File

@ -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<ast::FnDef>),
Struct(FileAstId<ast::StructDef>),
Union(FileAstId<ast::StructDef>),
Enum(FileAstId<ast::EnumDef>),
Const(FileAstId<ast::ConstDef>),
Static(FileAstId<ast::StaticDef>),
@ -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())

View File

@ -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);

View File

@ -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 {

View File

@ -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<GenericDef> = 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<ModuleDef> for Option<TypableDef> {
fn from(def: ModuleDef) -> Option<TypableDef> {
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(),

View File

@ -20,6 +20,7 @@ pub(super) fn complete_struct_literal(acc: &mut Completions, ctx: &CompletionCon
}
// FIXME unions
AdtDef::Union(_) => (),
AdtDef::Enum(_) => (),
};
}

View File

@ -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)),

View File

@ -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)

View File

@ -57,6 +57,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
Some(Def(ModuleDef::Module(_))) => "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",