@@ -26,8 +26,11 @@ impl Compiler {
2626 /// collection.
2727 ///
2828 /// ## Return value
29- /// Returns he modified source code, with line tags added.
29+ /// Returns the modified source code, with line tags added.
3030 /// If all nodes already have line tags, returns `None`.
31+ #[ deprecated(
32+ note = "This method doesn't return the new tags, just the modified text which can cause issues with multiple files. Please use TagLines instead"
33+ ) ]
3134 pub fn add_tags_to_lines (
3235 contents : impl Into < String > ,
3336 existing_line_tags : Vec < LineId > ,
@@ -66,6 +69,71 @@ impl Compiler {
6669 Ok ( None )
6770 }
6871 }
72+
73+ /// Given Yarn source code, adds line tags to the ends of all lines
74+ /// that need one and do not already have one.
75+ ///
76+ /// This method ensures that it does not generate line
77+ /// tags that are already present in the file, or present in the
78+ /// `existing_line_tags` collection.
79+ ///
80+ /// Line tags are added to any line of source code that contains
81+ /// user-visible text: lines, options, and shortcut options.
82+ ///
83+ /// ## Parameters
84+ ///
85+ /// `contents`: The source code to add line tags
86+ /// to.
87+ /// `existing_line_tags`: The collection of line tags
88+ /// already exist elsewhere in the source code; the newly added
89+ /// line tags will not be duplicates of any in this
90+ /// collection.
91+ ///
92+ /// ## Return value
93+ /// Returns Tuple of the modified source code, with line tags
94+ /// added and the list of new line tags generated.
95+ pub fn tag_lines (
96+ contents : impl Into < String > ,
97+ existing_line_tags : Vec < LineId > ,
98+ ) -> crate :: Result < Option < ( String , Vec < LineId > ) > > {
99+ let contents = contents. into ( ) ;
100+ let chars: Vec < _ > = contents. chars ( ) . map ( |c| c as u32 ) . collect ( ) ;
101+ // First, get the parse tree for this source code.
102+ let file = File {
103+ file_name : "<input>" . to_string ( ) ,
104+ source : contents,
105+ } ;
106+ let ( parse_source, diagnostics) = parse_source ( & file, & chars) ;
107+ let tree = parse_source. tree . clone ( ) ;
108+ // Were there any error-level diagnostics?
109+ if diagnostics. has_errors ( ) {
110+ // We encountered a parse error. Bail here; we aren't confident in our ability to correctly insert a line tag.
111+ return Err ( CompilerError ( diagnostics) ) ;
112+ }
113+
114+ // Create the line listener, which will produce TextReplacements for each new line tag.
115+ let untagged_line_listener =
116+ Box :: new ( UntaggedLineListener :: new ( existing_line_tags, parse_source) ) ;
117+ let rewritten_nodes = untagged_line_listener. rewritten_lines . clone ( ) ;
118+ let rewrote_anything = untagged_line_listener. rewrote_anything . clone ( ) ;
119+
120+ // Walk the tree with this listener, and generate text replacements containing line tags.
121+ let untagged_line_listener =
122+ YarnSpinnerParserTreeWalker :: walk ( untagged_line_listener, tree. as_ref ( ) ) ;
123+ // Apply these text replacements to the original source and return it.
124+
125+ if rewrote_anything. load ( Ordering :: Relaxed ) {
126+ let result = rewritten_nodes. take ( ) ;
127+ let mut string = result. join ( "\n " ) ;
128+ string. push ( '\n' ) ;
129+ Ok ( Some ( (
130+ string,
131+ untagged_line_listener. existing_line_tags . clone ( ) ,
132+ ) ) )
133+ } else {
134+ Ok ( None )
135+ }
136+ }
69137}
70138
71139/// Parses a string of Yarn source code, and produces a [`FileParseResult`]
0 commit comments