@@ -68,6 +68,18 @@ module AccessPath {
6868 DataFlow:: Node getValue ( ) { result = getSsaDefinition ( ) .getRhsNode ( ) }
6969 }
7070
71+ /**
72+ * Appends a single property name onto the access path `base`, where
73+ * the empty string represents the empty access path.
74+ */
75+ bindingset [ base, prop]
76+ private string join ( string base , string prop ) {
77+ base = "" and result = prop
78+ or
79+ base != "" and
80+ result = base + "." + prop
81+ }
82+
7183 /**
7284 * Gets the access path relative to `root` referred to by `node`.
7385 *
@@ -77,8 +89,8 @@ module AccessPath {
7789 * Examples:
7890 * ```
7991 * function f(x) {
80- * let a = x.f.g; // access path relative to 'x' is '. f.g'
81- * let b = a.h; // access path relative to 'x' is '. f.g.h'
92+ * let a = x.f.g; // access path relative to 'x' is 'f.g'
93+ * let b = a.h; // access path relative to 'x' is 'f.g.h'
8294 * }
8395 * ```
8496 */
@@ -102,7 +114,7 @@ module AccessPath {
102114 or
103115 not node .accessesGlobal ( _) and
104116 exists ( DataFlow:: PropRead prop | node = prop |
105- result = fromReference ( prop .getBase ( ) , root ) + "." + prop .getPropertyName ( )
117+ result = join ( fromReference ( prop .getBase ( ) , root ) , prop .getPropertyName ( ) )
106118 )
107119 or
108120 exists ( Closure:: ClosureNamespaceAccess acc | node = acc |
@@ -112,7 +124,7 @@ module AccessPath {
112124 or
113125 exists ( PropertyProjection proj | node = proj |
114126 proj .isSingletonProjection ( ) and
115- result = fromReference ( proj .getObject ( ) , root ) + "." + proj .getASelector ( )
127+ result = join ( fromReference ( proj .getObject ( ) , root ) , proj .getASelector ( ) . getStringValue ( ) )
116128 )
117129 or
118130 // Treat 'e || {}' as having the same name as 'e'
@@ -179,7 +191,7 @@ module AccessPath {
179191 * Only holds for the immediate right-hand side of an assignment or property, not
180192 * for nodes that transitively flow there.
181193 *
182- * For example, the class nodes below all map to `. foo.bar` relative to `x`:
194+ * For example, the class nodes below all map to `foo.bar` relative to `x`:
183195 * ```
184196 * function f(x) {
185197 * x.foo.bar = class {};
@@ -193,7 +205,7 @@ module AccessPath {
193205 private string fromRhs ( DataFlow:: Node node , Root root ) {
194206 exists ( DataFlow:: PropWrite write , string baseName |
195207 node = write .getRhs ( ) and
196- result = baseName + "." + write .getPropertyName ( )
208+ result = join ( baseName , write .getPropertyName ( ) )
197209 |
198210 baseName = fromReference ( write .getBase ( ) , root )
199211 or
@@ -237,13 +249,11 @@ module AccessPath {
237249 *
238250 * This works for direct references as well as for aliases established through local data flow.
239251 *
240- * Note that non-empty access paths contain an initial `.`, such as in `.foo.bar`.
241- *
242252 * For example:
243253 * ```
244254 * function f(x) {
245- * let a = x.f.g; // reference to (x, ". f.g")
246- * let b = a.h; // reference to (x, ". f.g.h")
255+ * let a = x.f.g; // reference to (x, "f.g")
256+ * let b = a.h; // reference to (x, "f.g.h")
247257 * }
248258 * ```
249259 */
@@ -279,9 +289,7 @@ module AccessPath {
279289 * Only gets the immediate right-hand side of an assignment or property, not
280290 * nodes that transitively flow there.
281291 *
282- * Note that access paths contain an initial `.`, such as in `.foo.bar`.
283- *
284- * For example, the class nodes below are all assignments to `(x, ".foo.bar")`.
292+ * For example, the class nodes below are all assignments to `(x, "foo.bar")`.
285293 * ```
286294 * function f(x) {
287295 * x.foo.bar = class {};
0 commit comments