scanner, token: add column information to tokens (#9407)
							parent
							
								
									3753a58ce0
								
							
						
					
					
						commit
						aa4e22c287
					
				|  | @ -1440,6 +1440,7 @@ pub fn (expr Expr) position() token.Position { | |||
| 				line_nr: expr.pos.line_nr | ||||
| 				pos: left_pos.pos | ||||
| 				len: right_pos.pos - left_pos.pos + right_pos.len | ||||
| 				col: left_pos.col | ||||
| 				last_line: right_pos.last_line | ||||
| 			} | ||||
| 		} | ||||
|  | @ -1563,6 +1564,7 @@ pub fn (node Node) position() token.Position { | |||
| 						line_nr: -1 | ||||
| 						pos: -1 | ||||
| 						last_line: -1 | ||||
| 						col: -1 | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  |  | |||
|  | @ -4402,8 +4402,7 @@ fn (mut c Checker) at_expr(mut node ast.AtExpr) table.Type { | |||
| 			node.val = (node.pos.line_nr + 1).str() | ||||
| 		} | ||||
| 		.column_nr { | ||||
| 			_, column := util.filepath_pos_to_source_and_column(c.file.path, node.pos) | ||||
| 			node.val = (column + 1).str() | ||||
| 			node.val = (node.pos.col + 1).str() | ||||
| 		} | ||||
| 		.vhash { | ||||
| 			node.val = util.vhash() | ||||
|  |  | |||
|  | @ -257,6 +257,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr { | |||
| 		line_nr: match_first_pos.line_nr | ||||
| 		pos: match_first_pos.pos | ||||
| 		len: match_last_pos.pos - match_first_pos.pos + match_last_pos.len | ||||
| 		col: match_first_pos.col | ||||
| 	} | ||||
| 	if p.tok.kind == .rcbr { | ||||
| 		p.check(.rcbr) | ||||
|  | @ -401,6 +402,7 @@ fn (mut p Parser) select_expr() ast.SelectExpr { | |||
| 			line_nr: branch_first_pos.line_nr | ||||
| 			pos: branch_first_pos.pos | ||||
| 			len: branch_last_pos.pos - branch_first_pos.pos + branch_last_pos.len | ||||
| 			col: branch_first_pos.col | ||||
| 		} | ||||
| 		post_comments := p.eat_comments({}) | ||||
| 		pos.update_last_line(p.prev_tok.line_nr) | ||||
|  | @ -425,6 +427,7 @@ fn (mut p Parser) select_expr() ast.SelectExpr { | |||
| 		line_nr: match_first_pos.line_nr | ||||
| 		pos: match_first_pos.pos | ||||
| 		len: match_last_pos.pos - match_first_pos.pos + match_last_pos.len | ||||
| 		col: match_first_pos.col | ||||
| 	} | ||||
| 	if p.tok.kind == .rcbr { | ||||
| 		p.check(.rcbr) | ||||
|  |  | |||
|  | @ -389,6 +389,7 @@ fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit { | |||
| 				line_nr: first_field_pos.line_nr | ||||
| 				pos: first_field_pos.pos | ||||
| 				len: field_len | ||||
| 				col: first_field_pos.col | ||||
| 			} | ||||
| 		} | ||||
| 		i++ | ||||
|  |  | |||
|  | @ -26,7 +26,8 @@ pub mut: | |||
| 	text              string // the whole text of the file
 | ||||
| 	pos               int    // current position in the file, first character is s.text[0]
 | ||||
| 	line_nr           int    // current line number
 | ||||
| 	last_nl_pos       int    // for calculating column
 | ||||
| 	last_nl_pos       int = -1 // for calculating column
 | ||||
| 	is_crlf           bool   // special check when computing columns
 | ||||
| 	is_inside_string  bool   // set to true in a string, *at the start* of an $var or ${expr}
 | ||||
| 	is_inter_start    bool   // for hacky string interpolation TODO simplify
 | ||||
| 	is_inter_end      bool | ||||
|  | @ -177,6 +178,7 @@ fn (mut s Scanner) new_token(tok_kind token.Kind, lit string, len int) token.Tok | |||
| 		kind: tok_kind | ||||
| 		lit: lit | ||||
| 		line_nr: s.line_nr + line_offset | ||||
| 		col: mu.max(1, s.current_column() - len + 1) | ||||
| 		pos: s.pos - len + 1 | ||||
| 		len: len | ||||
| 		tidx: cidx | ||||
|  | @ -189,6 +191,7 @@ fn (s &Scanner) new_eof_token() token.Token { | |||
| 		kind: .eof | ||||
| 		lit: '' | ||||
| 		line_nr: s.line_nr + 1 | ||||
| 		col: 1 | ||||
| 		pos: s.pos | ||||
| 		len: 1 | ||||
| 		tidx: s.tidx | ||||
|  | @ -203,6 +206,7 @@ fn (mut s Scanner) new_multiline_token(tok_kind token.Kind, lit string, len int, | |||
| 		kind: tok_kind | ||||
| 		lit: lit | ||||
| 		line_nr: start_line + 1 | ||||
| 		col: mu.max(1, s.current_column() - len + 1) | ||||
| 		pos: s.pos - len + 1 | ||||
| 		len: len | ||||
| 		tidx: cidx | ||||
|  | @ -495,6 +499,9 @@ fn (mut s Scanner) skip_whitespace() { | |||
| 		if util.is_nl(s.text[s.pos]) && s.is_vh { | ||||
| 			return | ||||
| 		} | ||||
| 		if s.pos + 1 < s.text.len && s.text[s.pos] == `\r` && s.text[s.pos + 1] == `\n` { | ||||
| 			s.is_crlf = true | ||||
| 		} | ||||
| 		// Count \r\n as one line
 | ||||
| 		if util.is_nl(s.text[s.pos]) && !s.expect('\r\n', s.pos - 1) { | ||||
| 			s.inc_line_number() | ||||
|  | @ -863,19 +870,6 @@ fn (mut s Scanner) text_scan() token.Token { | |||
| 				} | ||||
| 				return s.new_token(.name, name, name.len) | ||||
| 			} | ||||
| 			/* | ||||
| 			case `\r`: | ||||
| 		if nextc == `\n` { | ||||
| 			s.pos++ | ||||
| 			s.last_nl_pos = s.pos | ||||
| 			return s.new_token(.nl, '') | ||||
| 		} | ||||
| 	 } | ||||
| 	case `\n`: | ||||
| 		s.last_nl_pos = s.pos | ||||
| 		return s.new_token(.nl, '') | ||||
| 	 } | ||||
| 			*/ | ||||
| 			`.` { | ||||
| 				if nextc == `.` { | ||||
| 					s.pos++ | ||||
|  | @ -1298,7 +1292,10 @@ fn (mut s Scanner) eat_to_end_of_line() { | |||
| 
 | ||||
| [inline] | ||||
| fn (mut s Scanner) inc_line_number() { | ||||
| 	s.last_nl_pos = s.pos | ||||
| 	s.last_nl_pos = mu.min(s.text.len - 1, s.pos) | ||||
| 	if s.is_crlf { | ||||
| 		s.last_nl_pos++ | ||||
| 	} | ||||
| 	s.line_nr++ | ||||
| 	s.line_ends << s.pos | ||||
| 	if s.line_nr > s.nr_lines { | ||||
|  | @ -1331,6 +1328,7 @@ pub fn (mut s Scanner) warn(msg string) { | |||
| 	pos := token.Position{ | ||||
| 		line_nr: s.line_nr | ||||
| 		pos: s.pos | ||||
| 		col: s.current_column() - 1 | ||||
| 	} | ||||
| 	if s.pref.output_mode == .stdout { | ||||
| 		eprintln(util.formatted_error('warning:', msg, s.file_path, pos)) | ||||
|  | @ -1348,6 +1346,7 @@ pub fn (mut s Scanner) error(msg string) { | |||
| 	pos := token.Position{ | ||||
| 		line_nr: s.line_nr | ||||
| 		pos: s.pos | ||||
| 		col: s.current_column() - 1 | ||||
| 	} | ||||
| 	if s.pref.output_mode == .stdout { | ||||
| 		eprintln(util.formatted_error('error:', msg, s.file_path, pos)) | ||||
|  | @ -1371,6 +1370,7 @@ fn (mut s Scanner) vet_error(msg string, fix vet.FixKind) { | |||
| 		file_path: s.file_path | ||||
| 		pos: token.Position{ | ||||
| 			line_nr: s.line_nr | ||||
| 			col: s.current_column() - 1 | ||||
| 		} | ||||
| 		kind: .error | ||||
| 		fix: fix | ||||
|  |  | |||
|  | @ -8,12 +8,13 @@ pub: | |||
| 	len     int // length of the literal in the source
 | ||||
| 	line_nr int // the line number in the source where the token occured
 | ||||
| 	pos     int // the position of the token in scanner text
 | ||||
| 	col     int // the column in the source where the token occured
 | ||||
| pub mut: | ||||
| 	last_line int // the line number where the ast object ends (used by vfmt)
 | ||||
| } | ||||
| 
 | ||||
| pub fn (pos Position) str() string { | ||||
| 	return 'Position{ line_nr: $pos.line_nr, last_line: $pos.last_line, pos: $pos.pos, len: $pos.len }' | ||||
| 	return 'Position{ line_nr: $pos.line_nr, last_line: $pos.last_line, pos: $pos.pos, col: $pos.col, len: $pos.len }' | ||||
| } | ||||
| 
 | ||||
| pub fn (pos Position) extend(end Position) Position { | ||||
|  | @ -30,6 +31,7 @@ pub fn (pos Position) extend_with_last_line(end Position, last_line int) Positio | |||
| 		line_nr: pos.line_nr | ||||
| 		last_line: last_line - 1 | ||||
| 		pos: pos.pos | ||||
| 		col: pos.col | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -44,5 +46,6 @@ pub fn (tok &Token) position() Position { | |||
| 		line_nr: tok.line_nr - 1 | ||||
| 		pos: tok.pos | ||||
| 		last_line: tok.line_nr - 1 | ||||
| 		col: tok.col - 1 | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ pub: | |||
| 	kind    Kind   // the token number/enum; for quick comparisons
 | ||||
| 	lit     string // literal representation of the token
 | ||||
| 	line_nr int    // the line number in the source where the token occured
 | ||||
| 	col     int    // the column in the source where the token occured
 | ||||
| 	// name_idx int // name table index for O(1) lookup
 | ||||
| 	pos  int // the position of the token in scanner text
 | ||||
| 	len  int // length of the literal
 | ||||
|  |  | |||
|  | @ -83,9 +83,9 @@ pub fn formatted_error(kind string, omsg string, filepath string, pos token.Posi | |||
| 		} | ||||
| 	} | ||||
| 	//
 | ||||
| 	source, column := filepath_pos_to_source_and_column(filepath, pos) | ||||
| 	position := '$path:${pos.line_nr + 1}:${mu.max(1, column + 1)}:' | ||||
| 	scontext := source_context(kind, source, column, pos).join('\n') | ||||
| 	source := read_file(filepath) or { '' } | ||||
| 	position := '$path:${pos.line_nr + 1}:${mu.max(1, pos.col + 1)}:' | ||||
| 	scontext := source_context(kind, source, pos).join('\n') | ||||
| 	final_position := bold(position) | ||||
| 	final_kind := bold(color(kind, kind)) | ||||
| 	final_msg := emsg | ||||
|  | @ -94,23 +94,7 @@ pub fn formatted_error(kind string, omsg string, filepath string, pos token.Posi | |||
| 	return '$final_position $final_kind $final_msg$final_context'.trim_space() | ||||
| } | ||||
| 
 | ||||
| pub fn filepath_pos_to_source_and_column(filepath string, pos token.Position) (string, int) { | ||||
| 	// TODO: optimize this; may be use a cache.
 | ||||
| 	// The column should not be so computationally hard to get.
 | ||||
| 	source := read_file(filepath) or { '' } | ||||
| 	mut p := mu.max(0, mu.min(source.len - 1, pos.pos)) | ||||
| 	if source.len > 0 { | ||||
| 		for ; p >= 0; p-- { | ||||
| 			if source[p] == `\n` || source[p] == `\r` { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	column := mu.max(0, pos.pos - p - 1) | ||||
| 	return source, column | ||||
| } | ||||
| 
 | ||||
| pub fn source_context(kind string, source string, column int, pos token.Position) []string { | ||||
| pub fn source_context(kind string, source string, pos token.Position) []string { | ||||
| 	mut clines := []string{} | ||||
| 	if source.len == 0 { | ||||
| 		return clines | ||||
|  | @ -121,8 +105,8 @@ pub fn source_context(kind string, source string, column int, pos token.Position | |||
| 	tab_spaces := '    ' | ||||
| 	for iline := bline; iline <= aline; iline++ { | ||||
| 		sline := source_lines[iline] | ||||
| 		start_column := mu.max(0, mu.min(column, sline.len)) | ||||
| 		end_column := mu.max(0, mu.min(column + mu.max(0, pos.len), sline.len)) | ||||
| 		start_column := mu.max(0, mu.min(pos.col, sline.len)) | ||||
| 		end_column := mu.max(0, mu.min(pos.col + mu.max(0, pos.len), sline.len)) | ||||
| 		cline := if iline == pos.line_nr { | ||||
| 			sline[..start_column] + color(kind, sline[start_column..end_column]) + | ||||
| 				sline[end_column..] | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue