From 1ad0779a007ed4a30d9e2443ab2e10d2ba041a1f Mon Sep 17 00:00:00 2001 From: Ariel Davis Date: Fri, 5 May 2023 17:35:20 -0700 Subject: [PATCH] Make WideEncoding non-exhaustive --- crates/ide-db/src/tests/line_index.rs | 9 ++------- crates/rust-analyzer/src/caps.rs | 11 ++++++----- crates/rust-analyzer/src/diagnostics/to_proto.rs | 12 +++++------- lib/line-index/src/lib.rs | 11 +++++++++++ 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/crates/ide-db/src/tests/line_index.rs b/crates/ide-db/src/tests/line_index.rs index c12936071d3..c41b0de5633 100644 --- a/crates/ide-db/src/tests/line_index.rs +++ b/crates/ide-db/src/tests/line_index.rs @@ -28,16 +28,11 @@ fn test_every_chars() { let got_lin_col = line_index.line_col(got_offset); assert_eq!(got_lin_col, lin_col); - for enc in [WideEncoding::Utf16, WideEncoding::Utf32] { + for (enc, col) in [(WideEncoding::Utf16, col_utf16), (WideEncoding::Utf32, col_utf32)] { let wide_lin_col = line_index.to_wide(enc, lin_col); let got_lin_col = line_index.to_utf8(enc, wide_lin_col); assert_eq!(got_lin_col, lin_col); - - let want_col = match enc { - WideEncoding::Utf16 => col_utf16, - WideEncoding::Utf32 => col_utf32, - }; - assert_eq!(wide_lin_col.col, want_col) + assert_eq!(wide_lin_col.col, col) } if c == '\n' { diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs index 3628670ac98..ab06b96814a 100644 --- a/crates/rust-analyzer/src/caps.rs +++ b/crates/rust-analyzer/src/caps.rs @@ -23,13 +23,14 @@ use crate::semantic_tokens; pub fn server_capabilities(config: &Config) -> ServerCapabilities { ServerCapabilities { - position_encoding: Some(match negotiated_encoding(config.caps()) { - PositionEncoding::Utf8 => PositionEncodingKind::UTF8, + position_encoding: match negotiated_encoding(config.caps()) { + PositionEncoding::Utf8 => Some(PositionEncodingKind::UTF8), PositionEncoding::Wide(wide) => match wide { - WideEncoding::Utf16 => PositionEncodingKind::UTF16, - WideEncoding::Utf32 => PositionEncodingKind::UTF32, + WideEncoding::Utf16 => Some(PositionEncodingKind::UTF16), + WideEncoding::Utf32 => Some(PositionEncodingKind::UTF32), + _ => None, }, - }), + }, text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { open_close: Some(true), change: Some(TextDocumentSyncKind::INCREMENTAL), diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index 415fa4e02f2..c8b2c4edb83 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -3,7 +3,6 @@ use std::collections::HashMap; use flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan}; -use ide_db::line_index::WideEncoding; use itertools::Itertools; use stdx::format_to; use vfs::{AbsPath, AbsPathBuf}; @@ -94,17 +93,16 @@ fn position( }; } let mut char_offset = 0; - let len_func = match position_encoding { - PositionEncoding::Utf8 => char::len_utf8, - PositionEncoding::Wide(WideEncoding::Utf16) => char::len_utf16, - PositionEncoding::Wide(WideEncoding::Utf32) => |_| 1, - }; for c in line.text.chars() { char_offset += 1; if char_offset > column_offset { break; } - true_column_offset += len_func(c) - 1; + let len = match position_encoding { + PositionEncoding::Utf8 => c.len_utf8(), + PositionEncoding::Wide(w) => w.measure(&c.to_string()), + }; + true_column_offset += len - 1; } } diff --git a/lib/line-index/src/lib.rs b/lib/line-index/src/lib.rs index 61f907f0604..40815bdcf19 100644 --- a/lib/line-index/src/lib.rs +++ b/lib/line-index/src/lib.rs @@ -20,6 +20,7 @@ pub struct LineCol { /// A kind of wide character encoding. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[non_exhaustive] pub enum WideEncoding { /// UTF-16. Utf16, @@ -27,6 +28,16 @@ pub enum WideEncoding { Utf32, } +impl WideEncoding { + /// Returns the number of units it takes to encode `text` in this encoding. + pub fn measure(&self, text: &str) -> usize { + match self { + WideEncoding::Utf16 => text.encode_utf16().count(), + WideEncoding::Utf32 => text.chars().count(), + } + } +} + /// Line/Column information in legacy encodings. // // Deliberately not a generic type and different from `LineCol`.