@@ -376,7 +376,14 @@ def _click_handler(view, url, hide_popup=False):
376
376
if hide_popup :
377
377
view .hide_popup ()
378
378
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 )
380
387
elif url .startswith ('replace:' ):
381
388
info = urllib .parse .parse_qs (url [8 :], keep_blank_values = True )
382
389
_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):
796
803
:param target_path: Absolute path to the top-level source file of the
797
804
target (lib.rs, main.rs, etc.). May be None if it is not known.
798
805
:param msg_cb: Callback that will be given the message object (and each
799
- child separately).
806
+ child separately). May be None.
800
807
"""
801
808
# cargo check emits in a slightly different format.
802
809
if 'reason' in info :
@@ -815,7 +822,7 @@ def add_rust_messages(window, base_path, info, target_path, msg_cb):
815
822
return
816
823
if _is_duplicate_message (window , primary_message ):
817
824
return
818
- batches = _batch_and_cross_link (primary_message )
825
+ batches = _batch_and_cross_link (window , primary_message )
819
826
_save_batches (window , batches , msg_cb )
820
827
821
828
@@ -830,8 +837,15 @@ def _is_duplicate_message(window, primary_message):
830
837
return False
831
838
832
839
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
835
849
836
850
837
851
def _collect_rust_messages (window , base_path , info , target_path ,
@@ -931,33 +945,31 @@ def set_primary_message(span, text):
931
945
message .text = text
932
946
message .level = level_from_str (info ['level' ])
933
947
934
- def add_additional (span , text , level , suggested_replacement = None ):
948
+ def add_additional (window , span , text , level , suggested_replacement = None ):
935
949
child = Message ()
936
950
child .text = text
937
951
child .suggested_replacement = suggested_replacement
938
952
child .level = level_from_str (level )
939
953
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 )
956
968
957
969
if len (info ['spans' ]) == 0 :
958
970
if parent_info :
959
971
# 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' ])
961
973
else :
962
974
# Messages without spans are global session messages (like "main
963
975
# function not found").
@@ -968,7 +980,9 @@ def add_additional(span, text, level, suggested_replacement=None):
968
980
imsg .startswith ('cannot continue' ) or
969
981
imsg .startswith ('Some errors occurred' ) or
970
982
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' )):
972
986
if target_path :
973
987
# Display at the bottom of the root path (like main.rs)
974
988
# for lack of a better place to put it.
@@ -990,7 +1004,7 @@ def find_span_r(span, expansion=None):
990
1004
return span , expansion
991
1005
992
1006
for span in info ['spans' ]:
993
- if _is_external_macro ( span ):
1007
+ if _is_external ( window , span [ 'file_name' ] ):
994
1008
# Rust gives the chain of expansions for the macro, which we don't
995
1009
# really care about. We want to find the site where the macro was
996
1010
# invoked. I'm not entirely confident this is the best way to do
@@ -1005,43 +1019,62 @@ def find_span_r(span, expansion=None):
1005
1019
updated ['suggested_replacement' ] = span ['suggested_replacement' ]
1006
1020
span = updated
1007
1021
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' ]):
1012
1023
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 ,),
1019
1053
info ['level' ])
1020
1054
text = '' .join ([x ['text' ] for x in span ['text' ]])
1021
- print ('macro text: `%s`' % (text ,))
1022
1055
if text :
1023
- add_additional (span ,
1056
+ add_additional (window , span ,
1024
1057
'Macro text: %s' % (text ,),
1025
1058
info ['level' ])
1026
1059
else :
1027
1060
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 ,
1030
1063
'this error originates in a macro outside of the current crate' ,
1031
1064
info ['level' ])
1032
1065
1033
1066
# Add a message for macro invocation site if available in the local
1034
1067
# crate.
1035
1068
if span ['expansion' ] and \
1036
- not _is_external_macro ( span ) and \
1069
+ not _is_external ( window , span [ 'file_name' ] ) and \
1037
1070
not span ['expansion' ]['macro_decl_name' ].startswith ('#[' ):
1038
1071
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' )
1040
1073
1041
1074
if span ['is_primary' ]:
1042
1075
if parent_info :
1043
1076
# Primary child message.
1044
- add_additional (span , info ['message' ], info ['level' ])
1077
+ add_additional (window , span , info ['message' ], info ['level' ])
1045
1078
else :
1046
1079
set_primary_message (span , info ['message' ])
1047
1080
@@ -1056,11 +1089,11 @@ def find_span_r(span, expansion=None):
1056
1089
# multiple spans (starting in 1.21).
1057
1090
if label is not None :
1058
1091
# Display the label for this Span.
1059
- add_additional (span , label , info ['level' ])
1092
+ add_additional (window , span , label , info ['level' ])
1060
1093
if span ['suggested_replacement' ] is not None :
1061
1094
# The "suggested_replacement" contains the code that should
1062
1095
# replace the span.
1063
- add_additional (span , None , 'help' ,
1096
+ add_additional (window , span , None , 'help' ,
1064
1097
suggested_replacement = span ['suggested_replacement' ])
1065
1098
1066
1099
# Recurse into children (which typically hold notes).
@@ -1070,19 +1103,24 @@ def find_span_r(span, expansion=None):
1070
1103
message )
1071
1104
1072
1105
1073
- def _batch_and_cross_link (primary_message ):
1106
+ def _batch_and_cross_link (window , primary_message ):
1074
1107
"""Creates a list of MessageBatch objects with appropriate cross links."""
1075
1108
def make_file_path (msg ):
1109
+ if _is_external (window , msg .path ):
1110
+ external = ':external'
1111
+ else :
1112
+ external = ''
1076
1113
if msg .span :
1077
- return 'file:///%s:%s:%s' % (
1114
+ return 'file:///%s:%s:%s%s ' % (
1078
1115
msg .path .replace ('\\ ' , '/' ),
1079
1116
msg .span [1 ][0 ] + 1 ,
1080
1117
msg .span [1 ][1 ] + 1 ,
1118
+ external ,
1081
1119
)
1082
1120
else :
1083
1121
# Arbitrarily large line number to force it to the bottom of the
1084
1122
# 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 )
1086
1124
1087
1125
# Group messages by line.
1088
1126
primary_batch = PrimaryBatch (primary_message )
0 commit comments