Don't make fields private unless you have to

This commit is contained in:
Aleksey Kladov 2020-08-17 16:11:29 +02:00
parent 0b2b9a5508
commit 6a4c9fc9fd
4 changed files with 45 additions and 33 deletions

View file

@ -66,13 +66,13 @@ pub struct GroupLabel(pub String);
#[derive(Debug, Clone)]
pub struct Assist {
id: AssistId,
pub id: AssistId,
/// Short description of the assist, as shown in the UI.
label: String,
group: Option<GroupLabel>,
pub group: Option<GroupLabel>,
/// Target ranges are used to sort assists: the smaller the target range,
/// the more specific assist is, and so it should be sorted first.
target: TextRange,
pub target: TextRange,
}
#[derive(Debug, Clone)]
@ -82,6 +82,11 @@ pub struct ResolvedAssist {
}
impl Assist {
fn new(id: AssistId, label: String, group: Option<GroupLabel>, target: TextRange) -> Assist {
assert!(label.starts_with(char::is_uppercase));
Assist { id, label, group, target }
}
/// Return all the assists applicable at the given position.
///
/// Assists are returned in the "unresolved" state, that is only labels are
@ -114,30 +119,8 @@ impl Assist {
acc.finish_resolved()
}
pub(crate) fn new(
id: AssistId,
label: String,
group: Option<GroupLabel>,
target: TextRange,
) -> Assist {
assert!(label.starts_with(|c: char| c.is_uppercase()));
Assist { id, label, group, target }
}
pub fn id(&self) -> AssistId {
self.id
}
pub fn label(&self) -> String {
self.label.clone()
}
pub fn group(&self) -> Option<GroupLabel> {
self.group.clone()
}
pub fn target(&self) -> TextRange {
self.target
pub fn label(&self) -> &str {
self.label.as_str()
}
}

View file

@ -859,10 +859,10 @@ pub(crate) fn handle_resolve_code_action(
.map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());
let assists = snap.analysis.resolved_assists(&snap.config.assist, frange)?;
let (id_string, index) = split_once(&params.id, ':').unwrap();
let (id, index) = split_once(&params.id, ':').unwrap();
let index = index.parse::<usize>().unwrap();
let assist = &assists[index];
assert!(assist.assist.id().0 == id_string);
assert!(assist.assist.id.0 == id);
Ok(to_proto::resolved_code_action(&snap, assist.clone())?.edit)
}

View file

@ -704,10 +704,10 @@ pub(crate) fn unresolved_code_action(
index: usize,
) -> Result<lsp_ext::CodeAction> {
let res = lsp_ext::CodeAction {
title: assist.label(),
id: Some(format!("{}:{}", assist.id().0.to_owned(), index.to_string())),
group: assist.group().filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0),
kind: Some(code_action_kind(assist.id().1)),
title: assist.label().to_string(),
id: Some(format!("{}:{}", assist.id.0, index.to_string())),
group: assist.group.filter(|_| snap.config.client_caps.code_action_group).map(|gr| gr.0),
kind: Some(code_action_kind(assist.id.1)),
edit: None,
is_preferred: None,
};

View file

@ -176,6 +176,35 @@ fn frobnicate(walrus: Option<Walrus>) {
}
```
# Getters & Setters
If a field can have any value without breaking invariants, make the field public.
Conversely, if there is an invariant, document it, enforce it in the "constructor" function, make the field private, and provide a getter.
Never provide setters.
Getters should return borrowed data:
```
struct Person {
// Invariant: never empty
first_name: String,
middle_name: Option<String>
}
// Good
impl Person {
fn first_name(&self) -> &str { self.first_name.as_str() }
fn middle_name(&self) -> Option<&str> { self.middle_name.as_ref() }
}
// Not as good
impl Person {
fn first_name(&self) -> String { self.first_name.clone() }
fn middle_name(&self) -> &Option<String> { &self.middle_name }
}
```
# Premature Pessimization
Avoid writing code which is slower than it needs to be.