@@ -18,6 +18,7 @@ use crate::ast::*;
18
18
use crate :: evaluator:: { EvaluationError , RestrictedEvaluator } ;
19
19
use crate :: extensions:: Extensions ;
20
20
use crate :: parser:: err:: ParseErrors ;
21
+ use crate :: parser:: Loc ;
21
22
use crate :: transitive_closure:: TCNode ;
22
23
use crate :: FromNormalizedStr ;
23
24
use itertools:: Itertools ;
@@ -62,13 +63,44 @@ impl std::fmt::Display for EntityType {
62
63
}
63
64
64
65
/// Unique ID for an entity. These represent entities in the AST.
65
- #[ derive( Serialize , Deserialize , PartialEq , Eq , Debug , Clone , Hash , PartialOrd , Ord ) ]
66
+ #[ derive( Serialize , Deserialize , Debug , Clone ) ]
66
67
#[ cfg_attr( feature = "arbitrary" , derive( arbitrary:: Arbitrary ) ) ]
67
68
pub struct EntityUID {
68
69
/// Typename of the entity
69
70
ty : EntityType ,
70
71
/// EID of the entity
71
72
eid : Eid ,
73
+ /// Location of the entity in policy source
74
+ #[ serde( skip) ]
75
+ loc : Option < Loc > ,
76
+ }
77
+
78
+ /// `PartialEq` implementation ignores the `loc`.
79
+ impl PartialEq for EntityUID {
80
+ fn eq ( & self , other : & Self ) -> bool {
81
+ self . ty == other. ty && self . eid == other. eid
82
+ }
83
+ }
84
+ impl Eq for EntityUID { }
85
+
86
+ impl std:: hash:: Hash for EntityUID {
87
+ fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
88
+ // hash the ty and eid, in line with the `PartialEq` impl which compares
89
+ // the ty and eid.
90
+ self . ty . hash ( state) ;
91
+ self . eid . hash ( state) ;
92
+ }
93
+ }
94
+
95
+ impl PartialOrd for EntityUID {
96
+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
97
+ Some ( self . cmp ( other) )
98
+ }
99
+ }
100
+ impl Ord for EntityUID {
101
+ fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
102
+ self . ty . cmp ( & other. ty ) . then ( self . eid . cmp ( & other. eid ) )
103
+ }
72
104
}
73
105
74
106
impl StaticallyTyped for EntityUID {
@@ -87,6 +119,7 @@ impl EntityUID {
87
119
Self {
88
120
ty : Self :: test_entity_type ( ) ,
89
121
eid : Eid ( eid. into ( ) ) ,
122
+ loc : None ,
90
123
}
91
124
}
92
125
// by default, Coverlay does not track coverage for lines after a line
@@ -113,6 +146,7 @@ impl EntityUID {
113
146
Ok ( Self {
114
147
ty : EntityType :: Specified ( Name :: parse_unqualified_name ( typename) ?) ,
115
148
eid : Eid ( eid. into ( ) ) ,
149
+ loc : None ,
116
150
} )
117
151
}
118
152
@@ -122,11 +156,17 @@ impl EntityUID {
122
156
( self . ty , self . eid )
123
157
}
124
158
159
+ /// Get the source location for this `EntityUID`.
160
+ pub fn loc ( & self ) -> & Option < Loc > {
161
+ & self . loc
162
+ }
163
+
125
164
/// Create a nominally-typed `EntityUID` with the given typename and EID
126
- pub fn from_components ( name : Name , eid : Eid ) -> Self {
165
+ pub fn from_components ( name : Name , eid : Eid , loc : Option < Loc > ) -> Self {
127
166
Self {
128
167
ty : EntityType :: Specified ( name) ,
129
168
eid,
169
+ loc,
130
170
}
131
171
}
132
172
@@ -135,6 +175,7 @@ impl EntityUID {
135
175
Self {
136
176
ty : EntityType :: Unspecified ,
137
177
eid,
178
+ loc : None ,
138
179
}
139
180
}
140
181
@@ -497,12 +538,14 @@ mod test {
497
538
let e2 = EntityUID :: from_components (
498
539
Name :: parse_unqualified_name ( "test_entity_type" ) . expect ( "should be a valid identifier" ) ,
499
540
Eid ( "foo" . into ( ) ) ,
541
+ None ,
500
542
) ;
501
543
let e3 = EntityUID :: unspecified_from_eid ( Eid ( "foo" . into ( ) ) ) ;
502
544
let e4 = EntityUID :: unspecified_from_eid ( Eid ( "bar" . into ( ) ) ) ;
503
545
let e5 = EntityUID :: from_components (
504
546
Name :: parse_unqualified_name ( "Unspecified" ) . expect ( "should be a valid identifier" ) ,
505
547
Eid ( "foo" . into ( ) ) ,
548
+ None ,
506
549
) ;
507
550
508
551
// an EUID is equal to itself
0 commit comments