Skip to content

Commit 65ed718

Browse files
authored
Merge pull request #432 from ehuss/message-filtering
Some improvements around message display.
2 parents 41ccdb1 + a9f4221 commit 65ed718

File tree

4 files changed

+101
-59
lines changed

4 files changed

+101
-59
lines changed

rust/messages.py

Lines changed: 85 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,14 @@ def _click_handler(view, url, hide_popup=False):
376376
if hide_popup:
377377
view.hide_popup()
378378
elif url.startswith('file:///'):
379-
view.window().open_file(url[8:], sublime.ENCODED_POSITION)
379+
path = url[8:]
380+
external = False
381+
if path.endswith(':external'):
382+
path = path[:-9]
383+
external = True
384+
new_view = view.window().open_file(path, sublime.ENCODED_POSITION)
385+
if external:
386+
new_view.set_read_only(True)
380387
elif url.startswith('replace:'):
381388
info = urllib.parse.parse_qs(url[8:], keep_blank_values=True)
382389
_accept_replace(view, info['id'][0], info['replacement'][0])
@@ -796,7 +803,7 @@ def add_rust_messages(window, base_path, info, target_path, msg_cb):
796803
:param target_path: Absolute path to the top-level source file of the
797804
target (lib.rs, main.rs, etc.). May be None if it is not known.
798805
:param msg_cb: Callback that will be given the message object (and each
799-
child separately).
806+
child separately). May be None.
800807
"""
801808
# cargo check emits in a slightly different format.
802809
if 'reason' in info:
@@ -815,7 +822,7 @@ def add_rust_messages(window, base_path, info, target_path, msg_cb):
815822
return
816823
if _is_duplicate_message(window, primary_message):
817824
return
818-
batches = _batch_and_cross_link(primary_message)
825+
batches = _batch_and_cross_link(window, primary_message)
819826
_save_batches(window, batches, msg_cb)
820827

821828

@@ -830,8 +837,15 @@ def _is_duplicate_message(window, primary_message):
830837
return False
831838

832839

833-
def _is_external_macro(span):
834-
return 'macros>' in span['file_name'] or span['file_name'].startswith('/rustc/')
840+
def _is_external(window, path):
841+
if 'macros>' in path:
842+
return True
843+
if not os.path.isabs(path):
844+
return False
845+
for folder in window.folders():
846+
if path.startswith(folder + os.sep):
847+
return False
848+
return True
835849

836850

837851
def _collect_rust_messages(window, base_path, info, target_path,
@@ -931,33 +945,31 @@ def set_primary_message(span, text):
931945
message.text = text
932946
message.level = level_from_str(info['level'])
933947

934-
def add_additional(span, text, level, suggested_replacement=None):
948+
def add_additional(window, span, text, level, suggested_replacement=None):
935949
child = Message()
936950
child.text = text
937951
child.suggested_replacement = suggested_replacement
938952
child.level = level_from_str(level)
939953
child.primary = False
940-
if _is_external_macro(span):
941-
# Nowhere to display this, just send it to the console via msg_cb.
942-
msg_cb(child)
943-
else:
944-
child.path = make_span_path(span)
945-
if not os.path.exists(child.path):
946-
# Sometimes rust gives messages that link to libstd in the
947-
# directory where it was built (such as on Travis).
948-
return
949-
child.span = make_span_region(span)
950-
if any(map(lambda m: m.is_similar(child), message.children)):
951-
# Duplicate message, skip. This happens with some of the
952-
# macro help messages.
953-
return
954-
child.parent = message
955-
message.children.append(child)
954+
child.path = make_span_path(span)
955+
if not os.path.exists(child.path):
956+
# Sometimes rust gives messages that link to libstd in the
957+
# directory where it was built (such as on CI).
958+
if msg_cb:
959+
msg_cb(child)
960+
return
961+
child.span = make_span_region(span)
962+
if any(map(lambda m: m.is_similar(child), message.children)):
963+
# Duplicate message, skip. This happens with some of the
964+
# macro help messages.
965+
return
966+
child.parent = message
967+
message.children.append(child)
956968

957969
if len(info['spans']) == 0:
958970
if parent_info:
959971
# This is extra info attached to the parent message.
960-
add_additional(parent_info['span'], info['message'], info['level'])
972+
add_additional(window, parent_info['span'], info['message'], info['level'])
961973
else:
962974
# Messages without spans are global session messages (like "main
963975
# function not found").
@@ -968,7 +980,9 @@ def add_additional(span, text, level, suggested_replacement=None):
968980
imsg.startswith('cannot continue') or
969981
imsg.startswith('Some errors occurred') or
970982
imsg.startswith('Some errors have detailed') or
971-
imsg.startswith('For more information about')):
983+
imsg.startswith('For more information about') or
984+
imsg.endswith('warning emitted') or
985+
imsg.endswith('warnings emitted')):
972986
if target_path:
973987
# Display at the bottom of the root path (like main.rs)
974988
# for lack of a better place to put it.
@@ -990,7 +1004,7 @@ def find_span_r(span, expansion=None):
9901004
return span, expansion
9911005

9921006
for span in info['spans']:
993-
if _is_external_macro(span):
1007+
if _is_external(window, span['file_name']):
9941008
# Rust gives the chain of expansions for the macro, which we don't
9951009
# really care about. We want to find the site where the macro was
9961010
# invoked. I'm not entirely confident this is the best way to do
@@ -1005,43 +1019,62 @@ def find_span_r(span, expansion=None):
10051019
updated['suggested_replacement'] = span['suggested_replacement']
10061020
span = updated
10071021

1008-
if _is_external_macro(span):
1009-
# Macros from extern crates do not have 'expansion', and thus
1010-
# we do not have a location to highlight. Place the result at
1011-
# the bottom of the primary target path.
1022+
if _is_external(window, span['file_name']):
10121023
macro_name = span['file_name']
1013-
if target_path:
1014-
span['file_name'] = target_path
1015-
span['line_start'] = None
1016-
# else, messages will be shown in console via msg_cb.
1017-
add_additional(span,
1018-
'Errors occurred in macro %s from external crate' % (macro_name,),
1024+
if not os.path.exists(span['file_name']):
1025+
# Macros from extern crates do not have 'expansion', and thus
1026+
# we do not have a location to highlight. Place the result at
1027+
# somewhere relevant.
1028+
if parent_info:
1029+
show_in_span = parent_info['span']
1030+
else:
1031+
for span in info['spans']:
1032+
if span['is_primary']:
1033+
show_in_span = span
1034+
break
1035+
else:
1036+
# This shouldn't happen.
1037+
show_in_span = None
1038+
1039+
if show_in_span:
1040+
span['file_name'] = show_in_span['file_name']
1041+
span['byte_start'] = show_in_span['byte_start']
1042+
span['byte_end'] = show_in_span['byte_end']
1043+
span['line_start'] = show_in_span['line_start']
1044+
span['line_end'] = show_in_span['line_end']
1045+
span['column_start'] = show_in_span['column_start']
1046+
span['column_end'] = show_in_span['column_end']
1047+
elif target_path:
1048+
span['file_name'] = target_path
1049+
span['line_start'] = None
1050+
# else, messages will be shown in console via msg_cb.
1051+
add_additional(window, span,
1052+
'Errors occurred in %s from external crate' % (macro_name,),
10191053
info['level'])
10201054
text = ''.join([x['text'] for x in span['text']])
1021-
print('macro text: `%s`' % (text,))
10221055
if text:
1023-
add_additional(span,
1056+
add_additional(window, span,
10241057
'Macro text: %s' % (text,),
10251058
info['level'])
10261059
else:
10271060
if not expansion or not expansion['def_site_span'] \
1028-
or _is_external_macro(expansion['def_site_span']):
1029-
add_additional(span,
1061+
or _is_external(window, expansion['def_site_span']['file_name']):
1062+
add_additional(window, span,
10301063
'this error originates in a macro outside of the current crate',
10311064
info['level'])
10321065

10331066
# Add a message for macro invocation site if available in the local
10341067
# crate.
10351068
if span['expansion'] and \
1036-
not _is_external_macro(span) and \
1069+
not _is_external(window, span['file_name']) and \
10371070
not span['expansion']['macro_decl_name'].startswith('#['):
10381071
invoke_span, expansion = find_span_r(span)
1039-
add_additional(invoke_span, 'in this macro invocation', 'help')
1072+
add_additional(window, invoke_span, 'in this macro invocation', 'help')
10401073

10411074
if span['is_primary']:
10421075
if parent_info:
10431076
# Primary child message.
1044-
add_additional(span, info['message'], info['level'])
1077+
add_additional(window, span, info['message'], info['level'])
10451078
else:
10461079
set_primary_message(span, info['message'])
10471080

@@ -1056,11 +1089,11 @@ def find_span_r(span, expansion=None):
10561089
# multiple spans (starting in 1.21).
10571090
if label is not None:
10581091
# Display the label for this Span.
1059-
add_additional(span, label, info['level'])
1092+
add_additional(window, span, label, info['level'])
10601093
if span['suggested_replacement'] is not None:
10611094
# The "suggested_replacement" contains the code that should
10621095
# replace the span.
1063-
add_additional(span, None, 'help',
1096+
add_additional(window, span, None, 'help',
10641097
suggested_replacement=span['suggested_replacement'])
10651098

10661099
# Recurse into children (which typically hold notes).
@@ -1070,19 +1103,24 @@ def find_span_r(span, expansion=None):
10701103
message)
10711104

10721105

1073-
def _batch_and_cross_link(primary_message):
1106+
def _batch_and_cross_link(window, primary_message):
10741107
"""Creates a list of MessageBatch objects with appropriate cross links."""
10751108
def make_file_path(msg):
1109+
if _is_external(window, msg.path):
1110+
external = ':external'
1111+
else:
1112+
external = ''
10761113
if msg.span:
1077-
return 'file:///%s:%s:%s' % (
1114+
return 'file:///%s:%s:%s%s' % (
10781115
msg.path.replace('\\', '/'),
10791116
msg.span[1][0] + 1,
10801117
msg.span[1][1] + 1,
1118+
external,
10811119
)
10821120
else:
10831121
# Arbitrarily large line number to force it to the bottom of the
10841122
# file, since we don't know ahead of time how large the file is.
1085-
return 'file:///%s:999999999' % (msg.path,)
1123+
return 'file:///%s:999999999%s' % (msg.path, external)
10861124

10871125
# Group messages by line.
10881126
primary_batch = PrimaryBatch(primary_message)

rust/themes.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def render(self, view, batch, for_popup=False):
125125
if isinstance(batch, PrimaryBatch):
126126
for url, path in batch.child_links:
127127
msgs.append(self.LINK_TMPL.format(
128-
url=url, text='See Also:', path=path))
128+
url=url, text=see_also(url), path=path))
129129
else:
130130
if batch.back_link:
131131
msgs.append(self.LINK_TMPL.format(
@@ -274,7 +274,7 @@ def icon(level):
274274
for url, path in batch.child_links:
275275
links.append(
276276
self.LINK_TMPL.format(
277-
url=url, text='See Also:', path=path))
277+
url=url, text=see_also(url), path=path))
278278
text = batch.primary_message.escaped_text(view, ' ' + icon('none'))
279279
if not text and not children:
280280
return None
@@ -327,8 +327,8 @@ def add_fake(msg, text):
327327
messages.append(fake)
328328

329329
if isinstance(batch, PrimaryBatch):
330-
for link in batch.child_links:
331-
add_fake(batch.primary_message, 'See Also: ' + link[1])
330+
for url, path in batch.child_links:
331+
add_fake(batch.primary_message, see_also(url) + ' ' + path)
332332
else:
333333
if batch.back_link:
334334
add_fake(batch.first(), 'See Primary: ' + batch.back_link[1])
@@ -340,3 +340,10 @@ def add_fake(msg, text):
340340
'solid': SolidTheme(),
341341
'test': TestTheme(),
342342
}
343+
344+
def see_also(path):
345+
print(path)
346+
if path.endswith(':external'):
347+
return 'See Also (external):'
348+
else:
349+
return 'See Also:'

tests/error-tests/tests/E0005.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn main() {
1515
// ^^^^^^^ERR pattern `None` not covered
1616
// ^^^^^^^ERR refutable pattern in local binding
1717
// ^^^^^^^MSG(>=1.39.0-beta,<1.44.0-beta) See Also: ↑:1
18-
// ^^^^^^^MSG(>=1.44.0-beta) See Also: ↓
18+
// ^^^^^^^MSG(>=1.44.0-beta) See Also (external): option.rs:
1919
// ^^^^^^^NOTE(>=1.40.0-beta) `let` bindings require
2020
// ^^^^^^^NOTE(>=1.40.0-beta) for more information
2121
// ^^^^^^^NOTE(>=1.44.0-beta) the matched value
@@ -25,6 +25,3 @@ fn main() {
2525
// Bug: https://github.com/rust-lang/rust/issues/64769
2626
// start-msg: ERR(>=1.39.0-beta,<1.44.0-beta) not covered
2727
// start-msg: MSG(>=1.39.0-beta,<1.44.0-beta) See Primary: ↓:14
28-
// end-msg: ERR(>=1.44.0-beta) Errors occurred in macro
29-
// end-msg: ERR(>=1.44.0-beta) not covered
30-
// end-msg: MSG(>=1.44.0-beta) See Primary: ↑:14

tests/error-tests/tests/impl-generic-mismatch.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ impl Hash for X {
5959
// ^^^^^^^^^^^ERR method `hash` has incompatible signature
6060
// ^^^^^^^^^^^ERR(>=1.28.0-beta) expected generic parameter
6161
// ^^^^^^^^^^^ERR(<1.28.0-beta) annotation in impl
62-
// ^^^^^^^^^^^MSG(>=1.32.0) See Also: ↓
62+
// ^^^^^^^^^^^ERR(>=1.32.0,<1.44.0-beta) Errors occurred in
63+
// ^^^^^^^^^^^ERR(>=1.32.0,<1.44.0-beta) Macro text:
64+
// ^^^^^^^^^^^ERR(>=1.32.0,<1.44.0-beta) method `hash` has incompatible
65+
// ^^^^^^^^^^^MSG(>=1.44.0-beta) See Also (external): mod.rs:
6366
}
64-
// end-msg: ERR(>=1.32.0) Errors occurred in macro
65-
// end-msg: ERR(>=1.32.0) declaration in trait here
66-
// end-msg: MSG(>=1.32.0) See Primary: ↑:58

0 commit comments

Comments
 (0)