Skip to content

Commit 1a06087

Browse files
authored
Tweak how we set IR source spans (#8531)
1 parent ff4782f commit 1a06087

File tree

3 files changed

+60
-30
lines changed

3 files changed

+60
-30
lines changed

edb/edgeql/compiler/stmt.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@
3030

3131
from collections import defaultdict
3232
import textwrap
33+
import itertools
3334

3435
from edb import errors
3536
from edb.common import ast
37+
from edb.common import span as edb_span
3638
from edb.common.typeutils import not_none
3739

3840
from edb.ir import ast as irast
@@ -1585,6 +1587,15 @@ def compile_query_subject(
15851587
if (shape is not None or view_scls is not None) and len(set.path_id) == 1:
15861588
ctx.class_view_overrides[set.path_id.target.id] = set_stype
15871589

1590+
if shape:
1591+
# make sure that an applied shape expands the span of the set
1592+
set.span = edb_span.merge_spans(
1593+
itertools.chain(
1594+
(s.span for s in [set] if s.span),
1595+
(el.span for el in shape if el.span)
1596+
)
1597+
)
1598+
15881599
return set
15891600

15901601

edb/edgeql/compiler/viewgen.py

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class EarlyShapePtr(NamedTuple):
9898
ptrcls: s_pointers.Pointer
9999
target_set: Optional[irast.Set]
100100
shape_origin: qlast.ShapeOrigin
101+
span: Optional[parsing.Span]
101102

102103

103104
class ShapePtr(NamedTuple):
@@ -106,6 +107,7 @@ class ShapePtr(NamedTuple):
106107
ptrcls: s_pointers.Pointer
107108
shape_op: qlast.ShapeOp
108109
target_set: Optional[irast.Set]
110+
span: Optional[parsing.Span]
109111

110112

111113
@dataclasses.dataclass(kw_only=True, frozen=True)
@@ -497,7 +499,8 @@ def make_error(
497499
)
498500

499501
pointers[pointer] = EarlyShapePtr(
500-
pointer, ptr_set, shape_el_desc.ql.origin)
502+
pointer, ptr_set, shape_el_desc.ql.origin, shape_el_desc.ql.span
503+
)
501504

502505
# If we are not defining a shape (so we might care about
503506
# materialization), look through our parent view (if one exists)
@@ -534,7 +537,8 @@ def make_error(
534537
)
535538

536539
pointers[pointer] = EarlyShapePtr(
537-
pointer, ptr_set, qlast.ShapeOrigin.MATERIALIZATION)
540+
pointer, ptr_set, qlast.ShapeOrigin.MATERIALIZATION, None
541+
)
538542

539543
specified_ptrs = {
540544
ptrcls.get_local_name(ctx.env.schema) for ptrcls in pointers
@@ -571,7 +575,7 @@ def make_error(
571575
set_shape = []
572576
shape_ptrs: list[ShapePtr] = []
573577

574-
for ptrcls, ptr_set, _ in pointers.values():
578+
for ptrcls, ptr_set, _, span in pointers.values():
575579
source: s_types.Type | s_pointers.PointerLike
576580

577581
if ptrcls.is_link_property(ctx.env.schema):
@@ -592,16 +596,15 @@ def make_error(
592596
continue
593597

594598
ctx.env.view_shapes[source].append((ptrcls, shape_op))
595-
shape_ptrs.append(ShapePtr(ir_set, ptrcls, shape_op, ptr_set))
599+
shape_ptrs.append(ShapePtr(ir_set, ptrcls, shape_op, ptr_set, span))
596600

597601
rptrcls = view_rptr.ptrcls if view_rptr else None
598602
shape_ptrs = _get_early_shape_configuration(
599603
ir_set, shape_ptrs, rptrcls=rptrcls, ctx=ctx)
600604

601605
# Produce the shape. The main thing here is that we need to fixup
602606
# all of the rptrs to properly point back at ir_set.
603-
for _, ptrcls, shape_op, ptr_set in shape_ptrs:
604-
ptr_span = None
607+
for _, ptrcls, shape_op, ptr_set, ptr_span in shape_ptrs:
605608
if ptrcls in ctx.env.pointer_specified_info:
606609
_, _, ptr_span = ctx.env.pointer_specified_info[ptrcls]
607610

@@ -636,7 +639,7 @@ def make_error(
636639
ir_set,
637640
ptrcls,
638641
same_computable_scope=True,
639-
span=ptr_span or span,
642+
span=ptr_span,
640643
ctx=ctx,
641644
)
642645

@@ -716,6 +719,7 @@ def _shape_el_ql_to_shape_el_desc(
716719
lexpr,
717720
],
718721
partial=True,
722+
span=shape_el.span,
719723
)
720724
else:
721725
path_ql = qlast.Path(
@@ -725,6 +729,7 @@ def _shape_el_ql_to_shape_el_desc(
725729
qlast.TypeIntersection(type=target_typexpr),
726730
],
727731
partial=True,
732+
span=shape_el.span,
728733
)
729734

730735
return ShapeElementDesc(
@@ -890,7 +895,8 @@ def _gen_pointers_from_defaults(
890895
)
891896

892897
result.append(EarlyShapePtr(
893-
pointer, ptr_set, qlast.ShapeOrigin.DEFAULT))
898+
pointer, ptr_set, qlast.ShapeOrigin.DEFAULT, None
899+
))
894900

895901
schema = ctx.env.schema
896902

@@ -900,11 +906,11 @@ def _gen_pointers_from_defaults(
900906
# We cannot check or preprocess this at migration time, because some
901907
# defaults may not be used for some inserts.
902908
pointer_indexes = {}
903-
for (index, (pointer, _, _)) in enumerate(result):
909+
for (index, (pointer, _, _, _)) in enumerate(result):
904910
p = pointer.get_nearest_non_derived_parent(schema)
905911
pointer_indexes[p.get_name(schema).name] = index
906912
graph = {}
907-
for (index, (_, irset, _)) in enumerate(result):
913+
for (index, (_, irset, _, _)) in enumerate(result):
908914
assert irset
909915
dep_pointers = ast.find_children(irset, irast.Pointer)
910916
dep_rptrs = (
@@ -1249,7 +1255,7 @@ def _compile_rewrites_for_stype(
12491255
ctx=scopectx,
12501256
)
12511257
res[pn] = EarlyShapePtr(
1252-
pointer, ptr_set, qlast.ShapeOrigin.DEFAULT
1258+
pointer, ptr_set, qlast.ShapeOrigin.DEFAULT, None
12531259
)
12541260
return res
12551261

@@ -2254,7 +2260,8 @@ def _inline_type_computable(
22542260
ctx.env.pointer_specified_info[ptr] = (None, None, None)
22552261
view_shape.insert(0, (ptr, qlast.ShapeOp.ASSIGN))
22562262
shape_ptrs.insert(
2257-
0, ShapePtr(ir_set, ptr, qlast.ShapeOp.ASSIGN, ptr_set))
2263+
0, ShapePtr(ir_set, ptr, qlast.ShapeOp.ASSIGN, ptr_set, None)
2264+
)
22582265

22592266

22602267
def _get_shape_configuration_inner(
@@ -2267,7 +2274,8 @@ def _get_shape_configuration_inner(
22672274
) -> None:
22682275
is_objtype = ir_set.path_id.is_objtype_path()
22692276
all_materialize = all(
2270-
op == qlast.ShapeOp.MATERIALIZE for _, _, op, _ in shape_ptrs)
2277+
op == qlast.ShapeOp.MATERIALIZE for _, _, op, _, _ in shape_ptrs
2278+
)
22712279

22722280
if is_objtype:
22732281
assert isinstance(stype, s_objtypes.ObjectType)
@@ -2306,7 +2314,8 @@ def _get_shape_configuration_inner(
23062314
view_shape.insert(0, (ptr, implicit_op))
23072315
shape_metadata.has_implicit_id = True
23082316
shape_ptrs.insert(
2309-
0, ShapePtr(ir_set, ptr, implicit_op, None))
2317+
0, ShapePtr(ir_set, ptr, implicit_op, None, None)
2318+
)
23102319
break
23112320

23122321
is_mutation = parent_view_type in {
@@ -2409,7 +2418,8 @@ def _get_late_shape_configuration(
24092418

24102419
for source in sources:
24112420
for ptr, shape_op in ctx.env.view_shapes[source]:
2412-
shape_ptrs.append(ShapePtr(ir_set, ptr, shape_op, None))
2421+
shape_ptrs.append(ShapePtr(ir_set, ptr, shape_op, None, None)
2422+
)
24132423

24142424
_get_shape_configuration_inner(
24152425
ir_set, shape_ptrs, stype, parent_view_type=parent_view_type, ctx=ctx)
@@ -2506,16 +2516,16 @@ def _late_compile_view_shapes_in_set(
25062516
return
25072517

25082518
shape = []
2509-
for path_tip, ptr, shape_op, _ in shape_ptrs:
2510-
span = None
2519+
for path_tip, ptr, shape_op, _, ptr_span in shape_ptrs:
2520+
ptr_span = None
25112521
if ptr in ctx.env.pointer_specified_info:
2512-
_, _, span = ctx.env.pointer_specified_info[ptr]
2522+
_, _, ptr_span = ctx.env.pointer_specified_info[ptr]
25132523

25142524
element = setgen.extend_path(
25152525
path_tip,
25162526
ptr,
25172527
same_computable_scope=True,
2518-
span=span,
2528+
span=ptr_span,
25192529
ctx=ctx,
25202530
)
25212531

tests/test_edgeql_explain.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ async def test_edgeql_explain_simple_01(self):
7272
''')
7373
self.assert_plan(res['fine_grained'], {
7474
"contexts": [
75-
{"buffer_idx": 0, "end": 32, "start": 28, "text": "User"}
75+
{
76+
"buffer_idx": 0,
77+
"start": 28,
78+
"end": 43,
79+
"text": "User { id, name"
80+
}
7681
],
7782
"pipeline": [
7883
{
@@ -356,9 +361,9 @@ async def test_edgeql_explain_multi_link_01(self):
356361
"contexts": [
357362
{
358363
"start": 28,
359-
"end": 32,
364+
"end": 60,
360365
"buffer_idx": 0,
361-
"text": "User",
366+
"text": "User { name, todo: {name, number",
362367
},
363368
],
364369
"pipeline": [
@@ -413,9 +418,9 @@ async def test_edgeql_explain_multi_link_01(self):
413418
"contexts": [
414419
{
415420
"start": 41,
416-
"end": 45,
421+
"end": 60,
417422
"buffer_idx": 0,
418-
"text": "todo",
423+
"text": "todo: {name, number",
419424
},
420425
],
421426
"pipeline": tb.bag([
@@ -606,9 +611,9 @@ async def test_edgeql_explain_computed_backlink_01(self):
606611
shape = {
607612
"contexts": [{
608613
"start": 28,
609-
"end": 32,
614+
"end": 68,
610615
"buffer_idx": 0,
611-
"text": "User"
616+
"text": "User { name, owned_issues: {name, number"
612617
}],
613618
"pipeline": [{
614619
"plan_rows": 1,
@@ -663,9 +668,9 @@ async def test_edgeql_explain_computed_backlink_01(self):
663668
"text": '.<owner[is default::Issue]'
664669
}, {
665670
"start": 41,
666-
"end": 53,
671+
"end": 68,
667672
"buffer_idx": 0,
668-
"text": "owned_issues"
673+
"text": "owned_issues: {name, number"
669674
}]),
670675
"pipeline": tb.bag([
671676
{
@@ -1020,9 +1025,13 @@ async def test_edgeql_explain_type_intersect_01(self):
10201025
"contexts": [
10211026
{
10221027
"start": 28,
1023-
"end": 32,
1028+
"end": 93,
10241029
"buffer_idx": 0,
1025-
"text": 'Text',
1030+
'text': (
1031+
'Text {\n'
1032+
' body,\n'
1033+
' z := [is Issue].name'
1034+
)
10261035
},
10271036
],
10281037
"pipeline": [

0 commit comments

Comments
 (0)