diff options
author | oxalica <[email protected]> | 2021-03-14 12:03:39 +0000 |
---|---|---|
committer | oxalica <[email protected]> | 2021-03-15 17:04:20 +0000 |
commit | ef416e0154767619fcbfa0d1682b28bd338a8ce9 (patch) | |
tree | e73269dbb569f176e9bba1b16eb74731d63c94c2 /crates/hir_ty/src/display.rs | |
parent | 2bb8956a102cb2efbea35e414a8214fba2efcaf6 (diff) |
Impl HirDisplay for function hover message
Diffstat (limited to 'crates/hir_ty/src/display.rs')
-rw-r--r-- | crates/hir_ty/src/display.rs | 203 |
1 files changed, 195 insertions, 8 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index c1062387e..c572bb114 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -5,7 +5,13 @@ use std::{borrow::Cow, fmt}; | |||
5 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | 6 | use chalk_ir::Mutability; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, | 8 | db::DefDatabase, |
9 | find_path, | ||
10 | generics::TypeParamProvenance, | ||
11 | item_scope::ItemInNs, | ||
12 | path::{GenericArg, Path, PathKind}, | ||
13 | type_ref::{TypeBound, TypeRef}, | ||
14 | visibility::Visibility, | ||
9 | AssocContainerId, Lookup, ModuleId, TraitId, | 15 | AssocContainerId, Lookup, ModuleId, TraitId, |
10 | }; | 16 | }; |
11 | use hir_expand::name::Name; | 17 | use hir_expand::name::Name; |
@@ -232,7 +238,7 @@ where | |||
232 | 238 | ||
233 | const TYPE_HINT_TRUNCATION: &str = "…"; | 239 | const TYPE_HINT_TRUNCATION: &str = "…"; |
234 | 240 | ||
235 | impl HirDisplay for &Ty { | 241 | impl<T: HirDisplay> HirDisplay for &'_ T { |
236 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 242 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
237 | HirDisplay::hir_fmt(*self, f) | 243 | HirDisplay::hir_fmt(*self, f) |
238 | } | 244 | } |
@@ -761,12 +767,6 @@ impl HirDisplay for TraitRef { | |||
761 | } | 767 | } |
762 | } | 768 | } |
763 | 769 | ||
764 | impl HirDisplay for &GenericPredicate { | ||
765 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
766 | HirDisplay::hir_fmt(*self, f) | ||
767 | } | ||
768 | } | ||
769 | |||
770 | impl HirDisplay for GenericPredicate { | 770 | impl HirDisplay for GenericPredicate { |
771 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 771 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
772 | if f.should_truncate() { | 772 | if f.should_truncate() { |
@@ -825,3 +825,190 @@ impl HirDisplay for Obligation { | |||
825 | } | 825 | } |
826 | } | 826 | } |
827 | } | 827 | } |
828 | |||
829 | pub fn write_visibility( | ||
830 | module_id: ModuleId, | ||
831 | vis: Visibility, | ||
832 | f: &mut HirFormatter, | ||
833 | ) -> Result<(), HirDisplayError> { | ||
834 | match vis { | ||
835 | Visibility::Public => write!(f, "pub "), | ||
836 | Visibility::Module(vis_id) => { | ||
837 | let def_map = module_id.def_map(f.db.upcast()); | ||
838 | let root_module_id = def_map.module_id(def_map.root()); | ||
839 | if vis_id == module_id { | ||
840 | // pub(self) or omitted | ||
841 | Ok(()) | ||
842 | } else if root_module_id == vis_id { | ||
843 | write!(f, "pub(crate) ") | ||
844 | } else if module_id.containing_module(f.db.upcast()) == Some(vis_id) { | ||
845 | write!(f, "pub(super) ") | ||
846 | } else { | ||
847 | write!(f, "pub(in ...) ") | ||
848 | } | ||
849 | } | ||
850 | } | ||
851 | } | ||
852 | |||
853 | impl HirDisplay for TypeRef { | ||
854 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
855 | match self { | ||
856 | TypeRef::Never => write!(f, "!")?, | ||
857 | TypeRef::Placeholder => write!(f, "_")?, | ||
858 | TypeRef::Tuple(elems) => { | ||
859 | write!(f, "(")?; | ||
860 | f.write_joined(elems, ", ")?; | ||
861 | if elems.len() == 1 { | ||
862 | write!(f, ",")?; | ||
863 | } | ||
864 | write!(f, ")")?; | ||
865 | } | ||
866 | TypeRef::Path(path) => path.hir_fmt(f)?, | ||
867 | TypeRef::RawPtr(inner, mutability) => { | ||
868 | let mutability = match mutability { | ||
869 | hir_def::type_ref::Mutability::Shared => "*const ", | ||
870 | hir_def::type_ref::Mutability::Mut => "*mut ", | ||
871 | }; | ||
872 | write!(f, "{}", mutability)?; | ||
873 | inner.hir_fmt(f)?; | ||
874 | } | ||
875 | TypeRef::Reference(inner, lifetime, mutability) => { | ||
876 | let mutability = match mutability { | ||
877 | hir_def::type_ref::Mutability::Shared => "", | ||
878 | hir_def::type_ref::Mutability::Mut => "mut ", | ||
879 | }; | ||
880 | write!(f, "&")?; | ||
881 | if let Some(lifetime) = lifetime { | ||
882 | write!(f, "{} ", lifetime.name)?; | ||
883 | } | ||
884 | write!(f, "{}", mutability)?; | ||
885 | inner.hir_fmt(f)?; | ||
886 | } | ||
887 | TypeRef::Array(inner) => { | ||
888 | write!(f, "[")?; | ||
889 | inner.hir_fmt(f)?; | ||
890 | // FIXME: Array length? | ||
891 | write!(f, "; _]")?; | ||
892 | } | ||
893 | TypeRef::Slice(inner) => { | ||
894 | write!(f, "[")?; | ||
895 | inner.hir_fmt(f)?; | ||
896 | write!(f, "]")?; | ||
897 | } | ||
898 | TypeRef::Fn(tys, is_varargs) => { | ||
899 | // FIXME: Function pointer qualifiers. | ||
900 | write!(f, "fn(")?; | ||
901 | f.write_joined(&tys[..tys.len() - 1], ", ")?; | ||
902 | if *is_varargs { | ||
903 | write!(f, "{}...", if tys.len() == 1 { "" } else { ", " })?; | ||
904 | } | ||
905 | write!(f, ")")?; | ||
906 | let ret_ty = tys.last().unwrap(); | ||
907 | match ret_ty { | ||
908 | TypeRef::Tuple(tup) if tup.is_empty() => {} | ||
909 | _ => { | ||
910 | write!(f, " -> ")?; | ||
911 | ret_ty.hir_fmt(f)?; | ||
912 | } | ||
913 | } | ||
914 | } | ||
915 | TypeRef::ImplTrait(bounds) => { | ||
916 | write!(f, "impl ")?; | ||
917 | f.write_joined(bounds, " + ")?; | ||
918 | } | ||
919 | TypeRef::DynTrait(bounds) => { | ||
920 | write!(f, "dyn ")?; | ||
921 | f.write_joined(bounds, " + ")?; | ||
922 | } | ||
923 | TypeRef::Error => write!(f, "{{error}}")?, | ||
924 | } | ||
925 | Ok(()) | ||
926 | } | ||
927 | } | ||
928 | |||
929 | impl HirDisplay for TypeBound { | ||
930 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
931 | match self { | ||
932 | TypeBound::Path(path) => path.hir_fmt(f), | ||
933 | TypeBound::Lifetime(lifetime) => write!(f, "{}", lifetime.name), | ||
934 | TypeBound::Error => write!(f, "{{error}}"), | ||
935 | } | ||
936 | } | ||
937 | } | ||
938 | |||
939 | impl HirDisplay for Path { | ||
940 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
941 | match (self.type_anchor(), self.kind()) { | ||
942 | (Some(anchor), _) => { | ||
943 | write!(f, "<")?; | ||
944 | anchor.hir_fmt(f)?; | ||
945 | write!(f, ">")?; | ||
946 | } | ||
947 | (_, PathKind::Plain) => {} | ||
948 | (_, PathKind::Abs) => write!(f, "::")?, | ||
949 | (_, PathKind::Crate) => write!(f, "crate")?, | ||
950 | (_, PathKind::Super(0)) => write!(f, "self")?, | ||
951 | (_, PathKind::Super(n)) => { | ||
952 | write!(f, "super")?; | ||
953 | for _ in 0..*n { | ||
954 | write!(f, "::super")?; | ||
955 | } | ||
956 | } | ||
957 | (_, PathKind::DollarCrate(_)) => write!(f, "{{extern_crate}}")?, | ||
958 | } | ||
959 | |||
960 | for (seg_idx, segment) in self.segments().iter().enumerate() { | ||
961 | if seg_idx != 0 { | ||
962 | write!(f, "::")?; | ||
963 | } | ||
964 | write!(f, "{}", segment.name)?; | ||
965 | if let Some(generic_args) = segment.args_and_bindings { | ||
966 | // We should be in type context, so format as `Foo<Bar>` instead of `Foo::<Bar>`. | ||
967 | // Do we actually format expressions? | ||
968 | write!(f, "<")?; | ||
969 | let mut first = true; | ||
970 | for arg in &generic_args.args { | ||
971 | if first { | ||
972 | first = false; | ||
973 | if generic_args.has_self_type { | ||
974 | // FIXME: Convert to `<Ty as Trait>` form. | ||
975 | write!(f, "Self = ")?; | ||
976 | } | ||
977 | } else { | ||
978 | write!(f, ", ")?; | ||
979 | } | ||
980 | arg.hir_fmt(f)?; | ||
981 | } | ||
982 | for binding in &generic_args.bindings { | ||
983 | if first { | ||
984 | first = false; | ||
985 | } else { | ||
986 | write!(f, ", ")?; | ||
987 | } | ||
988 | write!(f, "{}", binding.name)?; | ||
989 | match &binding.type_ref { | ||
990 | Some(ty) => { | ||
991 | write!(f, " = ")?; | ||
992 | ty.hir_fmt(f)? | ||
993 | } | ||
994 | None => { | ||
995 | write!(f, ": ")?; | ||
996 | f.write_joined(&binding.bounds, " + ")?; | ||
997 | } | ||
998 | } | ||
999 | } | ||
1000 | write!(f, ">")?; | ||
1001 | } | ||
1002 | } | ||
1003 | Ok(()) | ||
1004 | } | ||
1005 | } | ||
1006 | |||
1007 | impl HirDisplay for GenericArg { | ||
1008 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
1009 | match self { | ||
1010 | GenericArg::Type(ty) => ty.hir_fmt(f), | ||
1011 | GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), | ||
1012 | } | ||
1013 | } | ||
1014 | } | ||