chore: Prepare for Rust edition bump to 2024 (without autofix) (#27791)

Successor to #27779 - in this PR I've applied changes manually, without
futzing with if let lifetimes at all.

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2025-03-31 20:10:36 +02:00 committed by GitHub
parent d51aa2ffb0
commit 0729d24d77
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
162 changed files with 2333 additions and 1937 deletions

443
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1412,7 +1412,11 @@ impl ActiveThread {
)
}
fn render_tool_use(&self, tool_use: ToolUse, cx: &mut Context<Self>) -> impl IntoElement {
fn render_tool_use(
&self,
tool_use: ToolUse,
cx: &mut Context<Self>,
) -> impl IntoElement + use<> {
let is_open = self
.expanded_tool_uses
.get(&tool_use.id)

View file

@ -105,7 +105,7 @@ impl AssistantConfiguration {
&mut self,
provider: &Arc<dyn LanguageModelProvider>,
cx: &mut Context<Self>,
) -> impl IntoElement {
) -> impl IntoElement + use<> {
let provider_id = provider.id().0.clone();
let provider_name = provider.name().0.clone();
let configuration_view = self

View file

@ -687,7 +687,7 @@ pub fn refresh_context_store_text(
context_store: Entity<ContextStore>,
changed_buffers: &HashSet<Entity<Buffer>>,
cx: &App,
) -> impl Future<Output = Vec<ContextId>> {
) -> impl Future<Output = Vec<ContextId>> + use<> {
let mut tasks = Vec::new();
for context in &context_store.read(cx).context {
@ -855,7 +855,7 @@ fn refresh_thread_text(
fn refresh_context_buffer(
context_buffer: &ContextBuffer,
cx: &App,
) -> Option<impl Future<Output = ContextBuffer>> {
) -> Option<impl Future<Output = ContextBuffer> + use<>> {
let buffer = context_buffer.buffer.read(cx);
let path = buffer_path_log_err(buffer)?;
if buffer.version.changed_since(&context_buffer.version) {
@ -875,7 +875,7 @@ fn refresh_context_buffer(
fn refresh_context_symbol(
context_symbol: &ContextSymbol,
cx: &App,
) -> Option<impl Future<Output = ContextSymbol>> {
) -> Option<impl Future<Output = ContextSymbol> + use<>> {
let buffer = context_symbol.buffer.read(cx);
let path = buffer_path_log_err(buffer)?;
let project_path = buffer.project_path(cx)?;

View file

@ -1192,7 +1192,7 @@ impl Thread {
pub fn use_pending_tools(
&mut self,
cx: &mut Context<Self>,
) -> impl IntoIterator<Item = PendingToolUse> {
) -> impl IntoIterator<Item = PendingToolUse> + use<> {
let request = self.to_completion_request(RequestKind::Chat, cx);
let messages = Arc::new(request.messages);
let pending_tool_uses = self

View file

@ -3413,7 +3413,7 @@ impl ContextEditorToolbarItem {
pub fn render_remaining_tokens(
context_editor: &Entity<ContextEditor>,
cx: &App,
) -> Option<impl IntoElement> {
) -> Option<impl IntoElement + use<>> {
let context = &context_editor.read(cx).context;
let (token_count_color, token_count, max_token_count, tooltip) = match token_state(context, cx)?

View file

@ -105,8 +105,8 @@ impl JsonSchema for AssistantSettingsContent {
VersionedAssistantSettingsContent::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> Schema {
VersionedAssistantSettingsContent::json_schema(gen)
fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> Schema {
VersionedAssistantSettingsContent::json_schema(r#gen)
}
fn is_referenceable() -> bool {
@ -416,7 +416,7 @@ pub struct LanguageModelSelection {
pub model: String,
}
fn providers_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
fn providers_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
schemars::schema::SchemaObject {
enum_values: Some(vec![
"anthropic".into(),

View file

@ -221,7 +221,7 @@ fn collect_files(
project: Entity<Project>,
glob_inputs: &[String],
cx: &mut App,
) -> impl Stream<Item = Result<SlashCommandEvent>> {
) -> impl Stream<Item = Result<SlashCommandEvent>> + use<> {
let Ok(matchers) = glob_inputs
.into_iter()
.map(|glob_input| {
@ -782,7 +782,12 @@ mod test {
assert_eq!(result.sections[6].label, "summercamp");
assert_eq!(result.sections[7].label, separator!("zed/assets/themes"));
assert_eq!(result.text, separator!("zed/assets/themes\n```zed/assets/themes/LICENSE\n1\n```\n\nsummercamp\n```zed/assets/themes/summercamp/LICENSE\n1\n```\n\nsubdir\n```zed/assets/themes/summercamp/subdir/LICENSE\n1\n```\n\nsubsubdir\n```zed/assets/themes/summercamp/subdir/subsubdir/LICENSE\n3\n```\n\n"));
assert_eq!(
result.text,
separator!(
"zed/assets/themes\n```zed/assets/themes/LICENSE\n1\n```\n\nsummercamp\n```zed/assets/themes/summercamp/LICENSE\n1\n```\n\nsubdir\n```zed/assets/themes/summercamp/subdir/LICENSE\n1\n```\n\nsubsubdir\n```zed/assets/themes/summercamp/subdir/subsubdir/LICENSE\n3\n```\n\n"
)
);
// Ensure that the project lasts until after the last await
drop(project);

View file

@ -81,7 +81,9 @@ impl Tool for BashTool {
};
if worktrees.next().is_some() {
return Task::ready(Err(anyhow!("'.' is ambiguous in multi-root workspaces. Please specify a root directory explicitly.")));
return Task::ready(Err(anyhow!(
"'.' is ambiguous in multi-root workspaces. Please specify a root directory explicitly."
)));
}
only_worktree.read(cx).abs_path()

View file

@ -526,7 +526,8 @@ impl EditToolRequest {
}
}
write!(&mut output,
write!(
&mut output,
"The SEARCH section must exactly match an existing block of lines including all white \
space, comments, indentation, docstrings, etc."
)?;
@ -545,7 +546,8 @@ impl EditToolRequest {
}
if has_errors {
writeln!(&mut output,
writeln!(
&mut output,
"\n\nYou can fix errors by running the tool again. You can include instructions, \
but errors are part of the conversation so you don't need to repeat them.",
)?;

View file

@ -35,7 +35,7 @@ impl SoundRegistry {
cx.set_global(GlobalSoundRegistry(SoundRegistry::new(source)));
}
pub fn get(&self, name: &str) -> Result<impl Source<Item = f32>> {
pub fn get(&self, name: &str) -> Result<impl Source<Item = f32> + use<>> {
if let Some(wav) = self.cache.lock().get(name) {
return Ok(wav.clone());
}

View file

@ -32,7 +32,7 @@ impl AwsConnector for AwsHttpConnector {
let req = match request.try_into_http1x() {
Ok(req) => req,
Err(err) => {
return HttpConnectorFuture::ready(Err(ConnectorError::other(err.into(), None)))
return HttpConnectorFuture::ready(Err(ConnectorError::other(err.into(), None)));
}
};

View file

@ -433,79 +433,82 @@ impl BufferDiffInner {
let max_point = buffer.max_point();
let mut summaries = buffer.summaries_for_anchors_with_payload::<Point, _, _>(anchor_iter);
iter::from_fn(move || loop {
let (start_point, (start_anchor, start_base)) = summaries.next()?;
let (mut end_point, (mut end_anchor, end_base)) = summaries.next()?;
iter::from_fn(move || {
loop {
let (start_point, (start_anchor, start_base)) = summaries.next()?;
let (mut end_point, (mut end_anchor, end_base)) = summaries.next()?;
if !start_anchor.is_valid(buffer) {
continue;
}
if end_point.column > 0 && end_point < max_point {
end_point.row += 1;
end_point.column = 0;
end_anchor = buffer.anchor_before(end_point);
}
let mut secondary_status = DiffHunkSecondaryStatus::NoSecondaryHunk;
let mut has_pending = false;
if start_anchor
.cmp(&pending_hunks_cursor.start().buffer_range.start, buffer)
.is_gt()
{
pending_hunks_cursor.seek_forward(&start_anchor, Bias::Left, buffer);
}
if let Some(pending_hunk) = pending_hunks_cursor.item() {
let mut pending_range = pending_hunk.buffer_range.to_point(buffer);
if pending_range.end.column > 0 {
pending_range.end.row += 1;
pending_range.end.column = 0;
if !start_anchor.is_valid(buffer) {
continue;
}
if pending_range == (start_point..end_point) {
if !buffer.has_edits_since_in_range(
&pending_hunk.buffer_version,
start_anchor..end_anchor,
) {
has_pending = true;
secondary_status = pending_hunk.new_status;
}
if end_point.column > 0 && end_point < max_point {
end_point.row += 1;
end_point.column = 0;
end_anchor = buffer.anchor_before(end_point);
}
}
if let (Some(secondary_cursor), false) = (secondary_cursor.as_mut(), has_pending) {
let mut secondary_status = DiffHunkSecondaryStatus::NoSecondaryHunk;
let mut has_pending = false;
if start_anchor
.cmp(&secondary_cursor.start().buffer_range.start, buffer)
.cmp(&pending_hunks_cursor.start().buffer_range.start, buffer)
.is_gt()
{
secondary_cursor.seek_forward(&start_anchor, Bias::Left, buffer);
pending_hunks_cursor.seek_forward(&start_anchor, Bias::Left, buffer);
}
if let Some(secondary_hunk) = secondary_cursor.item() {
let mut secondary_range = secondary_hunk.buffer_range.to_point(buffer);
if secondary_range.end.column > 0 {
secondary_range.end.row += 1;
secondary_range.end.column = 0;
if let Some(pending_hunk) = pending_hunks_cursor.item() {
let mut pending_range = pending_hunk.buffer_range.to_point(buffer);
if pending_range.end.column > 0 {
pending_range.end.row += 1;
pending_range.end.column = 0;
}
if secondary_range.is_empty() && secondary_hunk.diff_base_byte_range.is_empty()
if pending_range == (start_point..end_point) {
if !buffer.has_edits_since_in_range(
&pending_hunk.buffer_version,
start_anchor..end_anchor,
) {
has_pending = true;
secondary_status = pending_hunk.new_status;
}
}
}
if let (Some(secondary_cursor), false) = (secondary_cursor.as_mut(), has_pending) {
if start_anchor
.cmp(&secondary_cursor.start().buffer_range.start, buffer)
.is_gt()
{
// ignore
} else if secondary_range == (start_point..end_point) {
secondary_status = DiffHunkSecondaryStatus::HasSecondaryHunk;
} else if secondary_range.start <= end_point {
secondary_status = DiffHunkSecondaryStatus::OverlapsWithSecondaryHunk;
secondary_cursor.seek_forward(&start_anchor, Bias::Left, buffer);
}
if let Some(secondary_hunk) = secondary_cursor.item() {
let mut secondary_range = secondary_hunk.buffer_range.to_point(buffer);
if secondary_range.end.column > 0 {
secondary_range.end.row += 1;
secondary_range.end.column = 0;
}
if secondary_range.is_empty()
&& secondary_hunk.diff_base_byte_range.is_empty()
{
// ignore
} else if secondary_range == (start_point..end_point) {
secondary_status = DiffHunkSecondaryStatus::HasSecondaryHunk;
} else if secondary_range.start <= end_point {
secondary_status = DiffHunkSecondaryStatus::OverlapsWithSecondaryHunk;
}
}
}
}
return Some(DiffHunk {
range: start_point..end_point,
diff_base_byte_range: start_base..end_base,
buffer_range: start_anchor..end_anchor,
secondary_status,
});
return Some(DiffHunk {
range: start_point..end_point,
diff_base_byte_range: start_base..end_base,
buffer_range: start_anchor..end_anchor,
secondary_status,
});
}
})
}
@ -776,7 +779,7 @@ impl BufferDiff {
language: Option<Arc<Language>>,
language_registry: Option<Arc<LanguageRegistry>>,
cx: &mut App,
) -> impl Future<Output = BufferDiffInner> {
) -> impl Future<Output = BufferDiffInner> + use<> {
let base_text_pair;
let base_text_exists;
let base_text_snapshot;
@ -818,7 +821,7 @@ impl BufferDiff {
base_text: Option<Arc<String>>,
base_text_snapshot: language::BufferSnapshot,
cx: &App,
) -> impl Future<Output = BufferDiffInner> {
) -> impl Future<Output = BufferDiffInner> + use<> {
let base_text_exists = base_text.is_some();
let base_text_pair = base_text.map(|text| (text, base_text_snapshot.as_rope().clone()));
cx.background_spawn(async move {
@ -2071,7 +2074,7 @@ mod tests {
)
});
let working_copy = working_copy.read_with(cx, |working_copy, _| working_copy.snapshot());
let mut index_text = if rng.gen() {
let mut index_text = if rng.r#gen() {
Rope::from(head_text.as_str())
} else {
working_copy.as_rope().clone()

View file

@ -243,7 +243,7 @@ impl Room {
}
}
fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> {
fn app_will_quit(&mut self, cx: &mut Context<Self>) -> impl Future<Output = ()> + use<> {
let task = if self.status.is_online() {
let leave = self.leave_internal(cx);
Some(cx.background_spawn(async move {
@ -665,7 +665,7 @@ impl Room {
Ok(())
}
pub fn room_update_completed(&mut self) -> impl Future<Output = ()> {
pub fn room_update_completed(&mut self) -> impl Future<Output = ()> + use<> {
let mut done_rx = self.room_update_completed_rx.clone();
async move {
while let Some(result) = done_rx.next().await {

View file

@ -183,7 +183,7 @@ impl ChannelChat {
let channel_id = self.channel_id;
let pending_id = ChannelMessageId::Pending(post_inc(&mut self.next_pending_message_id));
let nonce = self.rng.gen();
let nonce = self.rng.r#gen();
self.insert_messages(
SumTree::from_item(
ChannelMessage {
@ -257,7 +257,7 @@ impl ChannelChat {
cx,
);
let nonce: u128 = self.rng.gen();
let nonce: u128 = self.rng.r#gen();
let request = self.rpc.request(proto::UpdateChannelMessage {
channel_id: self.channel_id.0,

View file

@ -824,7 +824,10 @@ impl ChannelStore {
})
}
pub fn remove_channel(&self, channel_id: ChannelId) -> impl Future<Output = Result<()>> {
pub fn remove_channel(
&self,
channel_id: ChannelId,
) -> impl Future<Output = Result<()>> + use<> {
let client = self.client.clone();
async move {
client

View file

@ -465,7 +465,7 @@ mod linux {
match fork::fork() {
Ok(Fork::Parent(_)) => Ok(()),
Ok(Fork::Child) => {
std::env::set_var(FORCE_CLI_MODE_ENV_VAR_NAME, "");
unsafe { std::env::set_var(FORCE_CLI_MODE_ENV_VAR_NAME, "") };
if let Err(_) = fork::setsid() {
eprintln!("failed to setsid: {}", std::io::Error::last_os_error());
process::exit(1);
@ -521,7 +521,7 @@ mod flatpak {
paths.push(extra_path.into());
}
env::set_var("LD_LIBRARY_PATH", env::join_paths(paths).unwrap());
unsafe { env::set_var("LD_LIBRARY_PATH", env::join_paths(paths).unwrap()) };
}
/// Restarts outside of the sandbox if currently running within it
@ -562,7 +562,9 @@ mod flatpak {
{
if args.zed.is_none() {
args.zed = Some("/app/libexec/zed-editor".into());
env::set_var("ZED_UPDATE_EXPLANATION", "Please use flatpak to update zed");
unsafe {
env::set_var("ZED_UPDATE_EXPLANATION", "Please use flatpak to update zed")
};
}
}
args

View file

@ -817,7 +817,7 @@ impl Client {
| Status::Reauthenticating { .. }
| Status::ReconnectionError { .. } => false,
Status::Connected { .. } | Status::Connecting { .. } | Status::Reconnecting { .. } => {
return Ok(())
return Ok(());
}
Status::UpgradeRequired => return Err(EstablishConnectionError::UpgradeRequired)?,
};
@ -1024,7 +1024,7 @@ impl Client {
&self,
http: Arc<HttpClientWithUrl>,
release_channel: Option<ReleaseChannel>,
) -> impl Future<Output = Result<url::Url>> {
) -> impl Future<Output = Result<url::Url>> + use<> {
#[cfg(any(test, feature = "test-support"))]
let url_override = self.rpc_url.read().clone();
@ -1444,7 +1444,7 @@ impl Client {
pub fn request<T: RequestMessage>(
&self,
request: T,
) -> impl Future<Output = Result<T::Response>> {
) -> impl Future<Output = Result<T::Response>> + use<T> {
self.request_envelope(request)
.map_ok(|envelope| envelope.payload)
}
@ -1476,7 +1476,7 @@ impl Client {
pub fn request_envelope<T: RequestMessage>(
&self,
request: T,
) -> impl Future<Output = Result<TypedEnvelope<T::Response>>> {
) -> impl Future<Output = Result<TypedEnvelope<T::Response>>> + use<T> {
let client_id = self.id();
log::debug!(
"rpc request start. client_id:{}. name:{}",
@ -1501,7 +1501,7 @@ impl Client {
&self,
envelope: proto::Envelope,
request_type: &'static str,
) -> impl Future<Output = Result<proto::Envelope>> {
) -> impl Future<Output = Result<proto::Envelope>> + use<> {
let client_id = self.id();
log::debug!(
"rpc request start. client_id:{}. name:{}",

View file

@ -273,14 +273,14 @@ impl Telemetry {
}
#[cfg(any(test, feature = "test-support"))]
fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> {
fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> + use<> {
Task::ready(())
}
// Skip calling this function in tests.
// TestAppContext ends up calling this function on shutdown and it panics when trying to find the TelemetrySettings
#[cfg(not(any(test, feature = "test-support")))]
fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> {
fn shutdown_telemetry(self: &Arc<Self>) -> impl Future<Output = ()> + use<> {
telemetry::event!("App Closed");
// TODO: close final edit period and make sure it's sent
Task::ready(())

View file

@ -581,7 +581,7 @@ impl UserStore {
})
}
pub fn clear_contacts(&self) -> impl Future<Output = ()> {
pub fn clear_contacts(&self) -> impl Future<Output = ()> + use<> {
let (tx, mut rx) = postage::barrier::channel();
self.update_contacts_tx
.unbounded_send(UpdateContacts::Clear(tx))

View file

@ -534,7 +534,9 @@ async fn poll_stripe_events(
if event_pages.page.has_more {
if pages_of_already_processed_events >= NUMBER_OF_ALREADY_PROCESSED_PAGES_BEFORE_WE_STOP
{
log::info!("Stripe events: stopping, saw {pages_of_already_processed_events} pages of already-processed events");
log::info!(
"Stripe events: stopping, saw {pages_of_already_processed_events} pages of already-processed events"
);
break;
} else {
log::info!("Stripe events: retrieving next page");

View file

@ -853,7 +853,7 @@ fn db_status_to_proto(
_ => {
return Err(anyhow!(
"Unexpected combination of status fields: {entry:?}"
))
));
}
};
Ok(proto::StatusEntry {

View file

@ -74,7 +74,7 @@ impl TestDb {
let mut rng = StdRng::from_entropy();
let url = format!(
"postgres://postgres@localhost/zed-test-{}",
rng.gen::<u128>()
rng.r#gen::<u128>()
);
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_io()

View file

@ -20,7 +20,7 @@ pub fn get_dotenv_vars(current_dir: impl AsRef<Path>) -> Result<Vec<(String, Str
pub fn load_dotenv() -> Result<()> {
for (key, value) in get_dotenv_vars("./crates/collab")? {
std::env::set_var(key, value);
unsafe { std::env::set_var(key, value) };
}
Ok(())
}

View file

@ -26,7 +26,7 @@ impl Executor {
}
}
pub fn sleep(&self, duration: Duration) -> impl Future<Output = ()> {
pub fn sleep(&self, duration: Duration) -> impl Future<Output = ()> + use<> {
let this = self.clone();
async move {
match this {

View file

@ -193,7 +193,9 @@ mod tests {
.to_vec();
assert_eq!(
String::from_utf8(response_body).unwrap(),
format!("access to {provider:?} models is not available in your region ({country_code})")
format!(
"access to {provider:?} models is not available in your region ({country_code})"
)
);
}
}

View file

@ -26,7 +26,7 @@ impl TestLlmDb {
let mut rng = StdRng::from_entropy();
let url = format!(
"postgres://postgres@localhost/zed-llm-test-{}",
rng.gen::<u128>()
rng.r#gen::<u128>()
);
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_io()

View file

@ -724,7 +724,7 @@ impl Server {
system_id: Option<String>,
send_connection_id: Option<oneshot::Sender<ConnectionId>>,
executor: Executor,
) -> impl Future<Output = ()> {
) -> impl Future<Output = ()> + use<> {
let this = self.clone();
let span = info_span!("handle connection", %address,
connection_id=field::Empty,

View file

@ -5103,7 +5103,9 @@ async fn test_project_search(
results.entry(buffer).or_insert(ranges);
}
SearchResult::LimitReached => {
panic!("Unexpectedly reached search limit in tests. If you do want to assert limit-reached, change this panic call.")
panic!(
"Unexpectedly reached search limit in tests. If you do want to assert limit-reached, change this panic call."
)
}
};
}
@ -5602,7 +5604,7 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it(
let definitions;
let buffer_b2;
if rng.gen() {
if rng.r#gen() {
definitions = project_b.update(cx_b, |p, cx| p.definition(&buffer_b1, 23, cx));
(buffer_b2, _) = project_b
.update(cx_b, |p, cx| {

View file

@ -279,7 +279,7 @@ impl RandomizedTest for ProjectCollaborationTest {
let project_root_name = root_name_for_project(&project, cx);
let mut paths = client.fs().paths(false);
paths.remove(0);
let new_root_path = if paths.is_empty() || rng.gen() {
let new_root_path = if paths.is_empty() || rng.r#gen() {
Path::new(path!("/")).join(plan.next_root_dir_name())
} else {
paths.choose(rng).unwrap().clone()
@ -309,7 +309,7 @@ impl RandomizedTest for ProjectCollaborationTest {
.choose(rng)
});
let Some(worktree) = worktree else { continue };
let is_dir = rng.gen::<bool>();
let is_dir = rng.r#gen::<bool>();
let mut full_path =
worktree.read_with(cx, |w, _| PathBuf::from(w.root_name()));
full_path.push(gen_file_name(rng));
@ -387,7 +387,7 @@ impl RandomizedTest for ProjectCollaborationTest {
language::Bias::Left,
)
});
let detach = rng.gen();
let detach = rng.r#gen();
break ClientOperation::RequestLspDataInBuffer {
project_root_name,
full_path,
@ -460,7 +460,7 @@ impl RandomizedTest for ProjectCollaborationTest {
// Create or update a file or directory
96.. => {
let is_dir = rng.gen::<bool>();
let is_dir = rng.r#gen::<bool>();
let content;
let mut path;
let dir_paths = client.fs().directories(false);
@ -1315,7 +1315,9 @@ impl RandomizedTest for ProjectCollaborationTest {
match (host_file, guest_file) {
(Some(host_file), Some(guest_file)) => {
assert_eq!(guest_file.path(), host_file.path());
assert_eq!(guest_file.disk_state(), host_file.disk_state(),
assert_eq!(
guest_file.disk_state(),
host_file.disk_state(),
"guest {} disk_state does not match host {} for path {:?} in project {}",
guest_user_id,
host_user_id,
@ -1347,52 +1349,54 @@ impl RandomizedTest for ProjectCollaborationTest {
.base_text_string()
});
assert_eq!(
guest_diff_base, host_diff_base,
"guest {} diff base does not match host's for path {path:?} in project {project_id}",
client.username
);
guest_diff_base, host_diff_base,
"guest {} diff base does not match host's for path {path:?} in project {project_id}",
client.username
);
let host_saved_version =
host_buffer.read_with(host_cx, |b, _| b.saved_version().clone());
let guest_saved_version =
guest_buffer.read_with(client_cx, |b, _| b.saved_version().clone());
assert_eq!(
guest_saved_version, host_saved_version,
"guest {} saved version does not match host's for path {path:?} in project {project_id}",
client.username
);
guest_saved_version, host_saved_version,
"guest {} saved version does not match host's for path {path:?} in project {project_id}",
client.username
);
let host_is_dirty = host_buffer.read_with(host_cx, |b, _| b.is_dirty());
let guest_is_dirty = guest_buffer.read_with(client_cx, |b, _| b.is_dirty());
assert_eq!(
guest_is_dirty, host_is_dirty,
"guest {} dirty state does not match host's for path {path:?} in project {project_id}",
client.username
);
guest_is_dirty, host_is_dirty,
"guest {} dirty state does not match host's for path {path:?} in project {project_id}",
client.username
);
let host_saved_mtime = host_buffer.read_with(host_cx, |b, _| b.saved_mtime());
let guest_saved_mtime =
guest_buffer.read_with(client_cx, |b, _| b.saved_mtime());
assert_eq!(
guest_saved_mtime, host_saved_mtime,
"guest {} saved mtime does not match host's for path {path:?} in project {project_id}",
client.username
);
guest_saved_mtime, host_saved_mtime,
"guest {} saved mtime does not match host's for path {path:?} in project {project_id}",
client.username
);
let host_is_dirty = host_buffer.read_with(host_cx, |b, _| b.is_dirty());
let guest_is_dirty = guest_buffer.read_with(client_cx, |b, _| b.is_dirty());
assert_eq!(guest_is_dirty, host_is_dirty,
"guest {} dirty status does not match host's for path {path:?} in project {project_id}",
client.username
);
assert_eq!(
guest_is_dirty, host_is_dirty,
"guest {} dirty status does not match host's for path {path:?} in project {project_id}",
client.username
);
let host_has_conflict = host_buffer.read_with(host_cx, |b, _| b.has_conflict());
let guest_has_conflict =
guest_buffer.read_with(client_cx, |b, _| b.has_conflict());
assert_eq!(guest_has_conflict, host_has_conflict,
"guest {} conflict status does not match host's for path {path:?} in project {project_id}",
client.username
);
assert_eq!(
guest_has_conflict, host_has_conflict,
"guest {} conflict status does not match host's for path {path:?} in project {project_id}",
client.username
);
}
}
}

View file

@ -332,7 +332,7 @@ impl ChatPanel {
.color(Color::Muted),
)
}),
)
);
}
Some(val) => val,
};

View file

@ -46,7 +46,7 @@ fn normalize_query(input: &str) -> String {
match (last_char, char) {
(Some(':'), ':') => continue,
(Some(last_char), char) if last_char.is_whitespace() && char.is_whitespace() => {
continue
continue;
}
_ => {
last_char = Some(char);

View file

@ -158,7 +158,7 @@ pub fn components() -> AllComponents {
let data = COMPONENT_DATA.read();
let mut all_components = AllComponents::new();
for (ref scope, name, description) in &data.components {
for (scope, name, description) in &data.components {
let preview = data.previews.get(name).cloned();
let component_name = SharedString::new_static(name);
let id = ComponentId(name);

View file

@ -244,7 +244,7 @@ impl ComponentPreview {
ix: usize,
entry: &PreviewEntry,
cx: &Context<Self>,
) -> impl IntoElement {
) -> impl IntoElement + use<> {
match entry {
PreviewEntry::Component(component_metadata) => {
let id = component_metadata.id();

View file

@ -2,7 +2,7 @@ use std::sync::Arc;
use collections::HashMap;
use gpui::App;
use schemars::gen::SchemaGenerator;
use schemars::r#gen::SchemaGenerator;
use schemars::schema::{InstanceType, Schema, SchemaObject};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

View file

@ -348,7 +348,10 @@ impl Copilot {
this
}
fn shutdown_language_server(&mut self, _cx: &mut Context<Self>) -> impl Future<Output = ()> {
fn shutdown_language_server(
&mut self,
_cx: &mut Context<Self>,
) -> impl Future<Output = ()> + use<> {
let shutdown = match mem::replace(&mut self.server, CopilotServer::Disabled) {
CopilotServer::Running(server) => Some(Box::pin(async move { server.lsp.shutdown() })),
_ => None,

View file

@ -296,7 +296,9 @@ impl DebugPanel {
match event {
dap_store::DapStoreEvent::DebugClientStarted(session_id) => {
let Some(session) = dap_store.read(cx).session_by_id(session_id) else {
return log::error!("Couldn't get session with id: {session_id:?} from DebugClientStarted event");
return log::error!(
"Couldn't get session with id: {session_id:?} from DebugClientStarted event"
);
};
let Some(project) = self.project.upgrade() else {

View file

@ -437,7 +437,9 @@ impl VariableList {
});
if res.is_none() {
log::error!("Couldn't confirm variable edit because variable doesn't have a leaf name or a parent reference id");
log::error!(
"Couldn't confirm variable edit because variable doesn't have a leaf name or a parent reference id"
);
}
}

View file

@ -49,7 +49,7 @@ impl<'a> CommitAvatar<'a> {
&'a self,
window: &mut Window,
cx: &mut Context<CommitTooltip>,
) -> Option<impl IntoElement> {
) -> Option<impl IntoElement + use<>> {
let remote = self
.commit
.message

View file

@ -1464,7 +1464,7 @@ pub mod tests {
});
let buffer = cx.update(|cx| {
if rng.gen() {
if rng.r#gen() {
let len = rng.gen_range(0..10);
let text = util::RandomCharIter::new(&mut rng)
.take(len)
@ -1526,7 +1526,7 @@ pub mod tests {
}
30..=44 => {
map.update(cx, |map, cx| {
if rng.gen() || blocks.is_empty() {
if rng.r#gen() || blocks.is_empty() {
let buffer = map.snapshot(cx).buffer_snapshot;
let block_properties = (0..rng.gen_range(1..=1))
.map(|_| {
@ -1536,7 +1536,7 @@ pub mod tests {
Bias::Left,
));
let placement = if rng.gen() {
let placement = if rng.r#gen() {
BlockPlacement::Above(position)
} else {
BlockPlacement::Below(position)
@ -1580,7 +1580,7 @@ pub mod tests {
});
}
if rng.gen() && fold_count > 0 {
if rng.r#gen() && fold_count > 0 {
log::info!("unfolding ranges: {:?}", ranges);
map.update(cx, |map, cx| {
map.unfold_intersecting(ranges, true, cx);

View file

@ -1370,7 +1370,7 @@ impl BlockSnapshot {
while let Some(transform) = cursor.item() {
match &transform.block {
Some(Block::ExcerptBoundary { excerpt, .. }) => {
return Some(StickyHeaderExcerpt { excerpt })
return Some(StickyHeaderExcerpt { excerpt });
}
Some(block) if block.is_buffer_header() => return None,
_ => {
@ -2913,7 +2913,7 @@ mod tests {
log::info!("Wrap width: {:?}", wrap_width);
log::info!("Excerpt Header Height: {:?}", excerpt_header_height);
let is_singleton = rng.gen();
let is_singleton = rng.r#gen();
let buffer = if is_singleton {
let len = rng.gen_range(0..10);
let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
@ -3077,7 +3077,9 @@ mod tests {
let fold = !unfolded_buffers.is_empty() && rng.gen_bool(0.5);
let unfold = !folded_buffers.is_empty() && rng.gen_bool(0.5);
if !fold && !unfold {
log::info!("Noop fold/unfold operation. Unfolded buffers: {unfolded_count}, folded buffers: {folded_count}");
log::info!(
"Noop fold/unfold operation. Unfolded buffers: {unfolded_count}, folded buffers: {folded_count}"
);
continue;
}

View file

@ -1616,7 +1616,7 @@ mod tests {
let len = rng.gen_range(0..10);
let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
let buffer = if rng.gen() {
let buffer = if rng.r#gen() {
MultiBuffer::build_simple(&text, cx)
} else {
MultiBuffer::build_random(&mut rng, cx)
@ -1962,7 +1962,7 @@ mod tests {
let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
to_unfold.push(start..end);
}
let inclusive = rng.gen();
let inclusive = rng.r#gen();
log::info!("unfolding {:?} (inclusive: {})", to_unfold, inclusive);
let (mut writer, snapshot, edits) = self.write(inlay_snapshot, vec![]);
snapshot_edits.push((snapshot, edits));

View file

@ -610,9 +610,9 @@ impl InlayMap {
let mut to_insert = Vec::new();
let snapshot = &mut self.snapshot;
for i in 0..rng.gen_range(1..=5) {
if self.inlays.is_empty() || rng.gen() {
if self.inlays.is_empty() || rng.r#gen() {
let position = snapshot.buffer.random_byte_range(0, rng).start;
let bias = if rng.gen() { Bias::Left } else { Bias::Right };
let bias = if rng.r#gen() { Bias::Left } else { Bias::Right };
let len = if rng.gen_bool(0.01) {
0
} else {
@ -1500,7 +1500,7 @@ mod tests {
.unwrap_or(10);
let len = rng.gen_range(0..30);
let buffer = if rng.gen() {
let buffer = if rng.r#gen() {
let text = util::RandomCharIter::new(&mut rng)
.take(len)
.collect::<String>();

View file

@ -738,7 +738,7 @@ mod tests {
fn test_random_tabs(cx: &mut gpui::App, mut rng: StdRng) {
let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap();
let len = rng.gen_range(0..30);
let buffer = if rng.gen() {
let buffer = if rng.r#gen() {
let text = util::RandomCharIter::new(&mut rng)
.take(len)
.collect::<String>();

View file

@ -1207,7 +1207,7 @@ mod tests {
log::info!("Wrap width: {:?}", wrap_width);
let buffer = cx.update(|cx| {
if rng.gen() {
if rng.r#gen() {
MultiBuffer::build_random(&mut rng, cx)
} else {
let len = rng.gen_range(0..10);

View file

@ -2428,7 +2428,11 @@ impl Editor {
background_executor.timer(SERIALIZATION_THROTTLE_TIME).await;
DB.save_editor_folds(editor_id, workspace_id, db_folds)
.await
.with_context(|| format!("persisting editor folds for editor {editor_id}, workspace {workspace_id:?}"))
.with_context(|| {
format!(
"persisting editor folds for editor {editor_id}, workspace {workspace_id:?}"
)
})
.log_err();
});
}
@ -6200,7 +6204,9 @@ impl Editor {
fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
if self.tasks.insert(key, value).is_some() {
// This case should hopefully be rare, but just in case...
log::error!("multiple different run targets found on a single line, only the last target will be rendered")
log::error!(
"multiple different run targets found on a single line, only the last target will be rendered"
)
}
}

View file

@ -7985,7 +7985,9 @@ async fn test_multibuffer_format_during_save(cx: &mut TestAppContext) {
assert!(cx.read(|cx| !multi_buffer_editor.is_dirty(cx)));
assert_eq!(
multi_buffer_editor.update(cx, |editor, cx| editor.text(cx)),
uri!("a|o[file:///a/main.rs formatted]bbbb\ncccc\n\nffff\ngggg\n\njjjj\n\nlll[file:///a/other.rs formatted]mmmm\nnnnn|four|five|six|\nr\n\nuuuu\n\nvvvv\nwwww\nxxxx\n\n{{{{\n||||\n\n\u{7f}\u{7f}\u{7f}\u{7f}"),
uri!(
"a|o[file:///a/main.rs formatted]bbbb\ncccc\n\nffff\ngggg\n\njjjj\n\nlll[file:///a/other.rs formatted]mmmm\nnnnn|four|five|six|\nr\n\nuuuu\n\nvvvv\nwwww\nxxxx\n\n{{{{\n||||\n\n\u{7f}\u{7f}\u{7f}\u{7f}"
),
);
buffer_1.update(cx, |buffer, _| {
assert!(!buffer.is_dirty());
@ -18669,7 +18671,7 @@ fn assert_selection_ranges(marked_text: &str, editor: &mut Editor, cx: &mut Cont
pub fn handle_signature_help_request(
cx: &mut EditorLspTestContext,
mocked_response: lsp::SignatureHelp,
) -> impl Future<Output = ()> {
) -> impl Future<Output = ()> + use<> {
let mut request =
cx.set_request_handler::<lsp::request::SignatureHelpRequest, _, _>(move |_, _, _| {
let mocked_response = mocked_response.clone();

View file

@ -4190,8 +4190,7 @@ impl EditorElement {
None;
for (&new_row, &new_background) in &layout.highlighted_rows {
match &mut current_paint {
Some((current_background, current_range, mut edges)) => {
let current_background = *current_background;
&mut Some((current_background, ref mut current_range, mut edges)) => {
let new_range_started = current_background != new_background
|| current_range.end.next_row() != new_row;
if new_range_started {
@ -8793,8 +8792,10 @@ mod tests {
px(500.0),
show_line_numbers,
);
assert!(invisibles.is_empty(),
"For editor mode {editor_mode_without_invisibles:?} no invisibles was expected but got {invisibles:?}");
assert!(
invisibles.is_empty(),
"For editor mode {editor_mode_without_invisibles:?} no invisibles was expected but got {invisibles:?}"
);
}
}
}
@ -8872,7 +8873,9 @@ mod tests {
(Invisible::Whitespace { .. }, Invisible::Whitespace { .. })
| (Invisible::Tab { .. }, Invisible::Tab { .. }) => {}
_ => {
panic!("At index {i}, expected invisible {expected_invisible:?} does not match actual {actual_invisible:?} by kind. Actual invisibles: {actual_invisibles:?}")
panic!(
"At index {i}, expected invisible {expected_invisible:?} does not match actual {actual_invisible:?} by kind. Actual invisibles: {actual_invisibles:?}"
)
}
},
None => {

View file

@ -26,8 +26,7 @@ use wit_component::ComponentEncoder;
/// Once Rust 1.78 is released, there will be a `wasm32-wasip2` target available, so we will
/// not need the adapter anymore.
const RUST_TARGET: &str = "wasm32-wasip1";
const WASI_ADAPTER_URL: &str =
"https://github.com/bytecodealliance/wasmtime/releases/download/v18.0.2/wasi_snapshot_preview1.reactor.wasm";
const WASI_ADAPTER_URL: &str = "https://github.com/bytecodealliance/wasmtime/releases/download/v18.0.2/wasi_snapshot_preview1.reactor.wasm";
/// Compiling Tree-sitter parsers from C to WASM requires Clang 17, and a WASM build of libc
/// and clang's runtime library. The `wasi-sdk` provides these binaries.
@ -100,7 +99,9 @@ impl ExtensionBuilder {
for (grammar_name, grammar_metadata) in &extension_manifest.grammars {
let snake_cased_grammar_name = grammar_name.to_case(Case::Snake);
if grammar_name.as_ref() != snake_cased_grammar_name.as_str() {
bail!("grammar name '{grammar_name}' must be written in snake_case: {snake_cased_grammar_name}");
bail!(
"grammar name '{grammar_name}' must be written in snake_case: {snake_cased_grammar_name}"
);
}
log::info!(

View file

@ -19,7 +19,7 @@ path = "src/extension_api.rs"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
wit-bindgen = "0.22"
wit-bindgen = "0.41"
[package.metadata.component]
target = { path = "wit" }

View file

@ -185,7 +185,7 @@ pub trait Extension: Send + Sync {
#[macro_export]
macro_rules! register_extension {
($extension_type:ty) => {
#[export_name = "init-extension"]
#[unsafe(export_name = "init-extension")]
pub extern "C" fn __init_extension() {
std::env::set_current_dir(std::env::var("PWD").unwrap()).unwrap();
zed_extension_api::register_extension(|| {

View file

@ -398,7 +398,7 @@ impl ExtensionStore {
&mut self,
modified_extension: Option<Arc<str>>,
cx: &mut Context<Self>,
) -> impl Future<Output = ()> {
) -> impl Future<Output = ()> + use<> {
let (tx, rx) = oneshot::channel();
self.reload_complete_senders.push(tx);
self.reload_tx

View file

@ -839,64 +839,64 @@ async fn test_query_history(cx: &mut gpui::TestAppContext) {
let history_after_third =
open_close_queried_buffer("sec", 1, "second.rs", &workspace, cx).await;
assert_eq!(
history_after_third,
vec![
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/third.rs")),
},
Some(PathBuf::from(path!("/src/test/third.rs")))
),
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/second.rs")),
},
Some(PathBuf::from(path!("/src/test/second.rs")))
),
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/first.rs")),
},
Some(PathBuf::from(path!("/src/test/first.rs")))
),
],
"Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
history_after_third,
vec![
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/third.rs")),
},
Some(PathBuf::from(path!("/src/test/third.rs")))
),
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/second.rs")),
},
Some(PathBuf::from(path!("/src/test/second.rs")))
),
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/first.rs")),
},
Some(PathBuf::from(path!("/src/test/first.rs")))
),
],
"Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
3rd item should be the first in the history, as the last opened."
);
);
let history_after_second_again =
open_close_queried_buffer("thi", 1, "third.rs", &workspace, cx).await;
assert_eq!(
history_after_second_again,
vec![
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/second.rs")),
},
Some(PathBuf::from(path!("/src/test/second.rs")))
),
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/third.rs")),
},
Some(PathBuf::from(path!("/src/test/third.rs")))
),
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/first.rs")),
},
Some(PathBuf::from(path!("/src/test/first.rs")))
),
],
"Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
history_after_second_again,
vec![
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/second.rs")),
},
Some(PathBuf::from(path!("/src/test/second.rs")))
),
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/third.rs")),
},
Some(PathBuf::from(path!("/src/test/third.rs")))
),
FoundPath::new(
ProjectPath {
worktree_id,
path: Arc::from(Path::new("test/first.rs")),
},
Some(PathBuf::from(path!("/src/test/first.rs")))
),
],
"Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
2nd item, as the last opened, 3rd item should go next as it was opened right before."
);
);
}
#[gpui::test]
@ -1656,15 +1656,15 @@ async fn test_nonexistent_history_items_not_shown(cx: &mut gpui::TestAppContext)
cx.simulate_input("rs");
picker.update(cx, |picker, _| {
assert_eq!(
collect_search_matches(picker).history,
vec![
PathBuf::from("test/first.rs"),
PathBuf::from("test/third.rs"),
],
"Should have all opened files in the history, except the ones that do not exist on disk"
);
});
assert_eq!(
collect_search_matches(picker).history,
vec![
PathBuf::from("test/first.rs"),
PathBuf::from("test/third.rs"),
],
"Should have all opened files in the history, except the ones that do not exist on disk"
);
});
}
#[gpui::test]

View file

@ -430,7 +430,7 @@ impl Fs for RealFs {
unsafe {
unsafe fn ns_string(string: &str) -> id {
NSString::alloc(nil).init_str(string).autorelease()
unsafe { NSString::alloc(nil).init_str(string).autorelease() }
}
let url: id = msg_send![class!(NSURL), fileURLWithPath: ns_string(path.to_string_lossy().as_ref())];
@ -591,7 +591,7 @@ impl Fs for RealFs {
(io::ErrorKind::NotFound, _) => Ok(None),
(io::ErrorKind::Other, Some(libc::ENOTDIR)) => Ok(None),
_ => Err(anyhow::Error::new(err)),
}
};
}
};

View file

@ -365,7 +365,7 @@ impl std::fmt::Display for StreamFlags {
}
#[link(name = "CoreServices", kind = "framework")]
extern "C" {
unsafe extern "C" {
pub fn FSEventsGetCurrentEventId() -> u64;
}

View file

@ -1548,7 +1548,7 @@ impl GitPanel {
&mut self,
window: &mut Window,
cx: &mut Context<Self>,
) -> impl Future<Output = Result<bool, anyhow::Error>> {
) -> impl Future<Output = Result<bool, anyhow::Error>> + use<> {
let repo = self.active_repository.clone();
let mut cx = window.to_async(cx);
@ -2007,7 +2007,7 @@ impl GitPanel {
&mut self,
window: &mut Window,
cx: &mut Context<Self>,
) -> impl Future<Output = anyhow::Result<Option<Remote>>> {
) -> impl Future<Output = anyhow::Result<Option<Remote>>> + use<> {
let repo = self.active_repository.clone();
let workspace = self.workspace.clone();
let mut cx = window.to_async(cx);

View file

@ -226,7 +226,7 @@ embed-resource = "3.0"
naga.workspace = true
[target.'cfg(target_os = "macos")'.build-dependencies]
bindgen = "0.70.0"
bindgen = "0.71"
cbindgen = { version = "0.28.0", default-features = false }
naga.workspace = true

View file

@ -68,7 +68,7 @@ pub trait Action: 'static + Send {
/// Optional JSON schema for the action's input data.
fn action_json_schema(
_: &mut schemars::gen::SchemaGenerator,
_: &mut schemars::r#gen::SchemaGenerator,
) -> Option<schemars::schema::Schema>
where
Self: Sized,
@ -167,7 +167,7 @@ impl Default for ActionRegistry {
struct ActionData {
pub build: ActionBuilder,
pub json_schema: fn(&mut schemars::gen::SchemaGenerator) -> Option<schemars::schema::Schema>,
pub json_schema: fn(&mut schemars::r#gen::SchemaGenerator) -> Option<schemars::schema::Schema>,
}
/// This type must be public so that our macros can build it in other crates.
@ -183,7 +183,7 @@ pub struct MacroActionData {
pub aliases: &'static [&'static str],
pub type_id: TypeId,
pub build: ActionBuilder,
pub json_schema: fn(&mut schemars::gen::SchemaGenerator) -> Option<schemars::schema::Schema>,
pub json_schema: fn(&mut schemars::r#gen::SchemaGenerator) -> Option<schemars::schema::Schema>,
}
inventory::collect!(MacroActionBuilder);
@ -271,7 +271,7 @@ impl ActionRegistry {
pub fn action_schemas(
&self,
generator: &mut schemars::gen::SchemaGenerator,
generator: &mut schemars::r#gen::SchemaGenerator,
) -> Vec<(SharedString, Option<schemars::schema::Schema>)> {
// Use the order from all_names so that the resulting schema has sensible order.
self.all_names
@ -310,7 +310,7 @@ macro_rules! actions {
Ok(Box::new(Self))
},
fn action_json_schema(
_: &mut gpui::private::schemars::gen::SchemaGenerator,
_: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
None
}
@ -347,7 +347,7 @@ macro_rules! action_as {
Ok(Box::new(Self))
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
None
}
@ -381,7 +381,7 @@ macro_rules! action_with_deprecated_aliases {
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
None
},
@ -412,7 +412,7 @@ macro_rules! impl_action_with_deprecated_aliases {
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
Some(<Self as gpui::private::schemars::JsonSchema>::json_schema(
generator,
@ -446,7 +446,7 @@ macro_rules! impl_actions {
Ok(std::boxed::Box::new(gpui::private::serde_json::from_value::<Self>(value)?))
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
Some(<Self as gpui::private::schemars::JsonSchema>::json_schema(
generator,
@ -479,7 +479,7 @@ macro_rules! impl_internal_actions {
)))
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
None
}
@ -509,7 +509,7 @@ macro_rules! impl_action_as {
))
},
fn action_json_schema(
generator: &mut gpui::private::schemars::gen::SchemaGenerator,
generator: &mut gpui::private::schemars::r#gen::SchemaGenerator,
) -> Option<gpui::private::schemars::schema::Schema> {
Some(<Self as gpui::private::schemars::JsonSchema>::json_schema(
generator,

View file

@ -1347,7 +1347,7 @@ impl App {
/// Get all non-internal actions that have been registered, along with their schemas.
pub fn action_schemas(
&self,
generator: &mut schemars::gen::SchemaGenerator,
generator: &mut schemars::r#gen::SchemaGenerator,
) -> Vec<(SharedString, Option<schemars::schema::Schema>)> {
self.actions.action_schemas(generator)
}

View file

@ -234,11 +234,11 @@ impl AsyncApp {
}
/// Run something using this entity and cx, when the returned struct is dropped
pub fn on_drop<T: 'static>(
pub fn on_drop<T: 'static, Callback: FnOnce(&mut T, &mut Context<T>) + 'static>(
&self,
entity: &WeakEntity<T>,
f: impl FnOnce(&mut T, &mut Context<T>) + 'static,
) -> util::Deferred<impl FnOnce()> {
f: Callback,
) -> util::Deferred<impl FnOnce() + use<T, Callback>> {
let entity = entity.clone();
let mut cx = self.clone();
util::defer(move || {

View file

@ -448,7 +448,10 @@ impl TestAppContext {
}
/// Returns a stream of notifications whenever the Entity is updated.
pub fn notifications<T: 'static>(&mut self, entity: &Entity<T>) -> impl Stream<Item = ()> {
pub fn notifications<T: 'static>(
&mut self,
entity: &Entity<T>,
) -> impl Stream<Item = ()> + use<T> {
let (tx, rx) = futures::channel::mpsc::unbounded();
self.update(|cx| {
cx.observe(entity, {

View file

@ -66,11 +66,15 @@ impl Arena {
where
F: FnOnce() -> T,
{
ptr::write(ptr, f());
unsafe {
ptr::write(ptr, f());
}
}
unsafe fn drop<T>(ptr: *mut u8) {
std::ptr::drop_in_place(ptr.cast::<T>());
unsafe {
std::ptr::drop_in_place(ptr.cast::<T>());
}
}
unsafe {

View file

@ -196,12 +196,12 @@ impl BackgroundExecutor {
}
#[cfg(not(any(test, feature = "test-support")))]
pub(crate) fn block_internal<R>(
pub(crate) fn block_internal<Fut: Future>(
&self,
_background_only: bool,
future: impl Future<Output = R>,
future: Fut,
timeout: Option<Duration>,
) -> Result<R, impl Future<Output = R>> {
) -> Result<Fut::Output, impl Future<Output = Fut::Output> + use<Fut>> {
use std::time::Instant;
let mut future = Box::pin(future);
@ -234,12 +234,12 @@ impl BackgroundExecutor {
#[cfg(any(test, feature = "test-support"))]
#[track_caller]
pub(crate) fn block_internal<R>(
pub(crate) fn block_internal<Fut: Future>(
&self,
background_only: bool,
future: impl Future<Output = R>,
future: Fut,
timeout: Option<Duration>,
) -> Result<R, impl Future<Output = R>> {
) -> Result<Fut::Output, impl Future<Output = Fut::Output> + use<Fut>> {
use std::sync::atomic::AtomicBool;
let mut future = Box::pin(future);
@ -291,8 +291,8 @@ impl BackgroundExecutor {
waiting_message = format!("\n waiting on: {}\n", waiting_hint);
}
panic!(
"parked with nothing left to run{waiting_message}{backtrace_message}",
)
"parked with nothing left to run{waiting_message}{backtrace_message}",
)
}
self.dispatcher.park(None);
}
@ -303,11 +303,11 @@ impl BackgroundExecutor {
/// Block the current thread until the given future resolves
/// or `duration` has elapsed.
pub fn block_with_timeout<R>(
pub fn block_with_timeout<Fut: Future>(
&self,
duration: Duration,
future: impl Future<Output = R>,
) -> Result<R, impl Future<Output = R>> {
future: Fut,
) -> Result<Fut::Output, impl Future<Output = Fut::Output> + use<Fut>> {
self.block_internal(true, future, Some(duration))
}
@ -365,7 +365,7 @@ impl BackgroundExecutor {
/// in tests, run an arbitrary number of tasks (determined by the SEED environment variable)
#[cfg(any(test, feature = "test-support"))]
pub fn simulate_random_delay(&self) -> impl Future<Output = ()> {
pub fn simulate_random_delay(&self) -> impl Future<Output = ()> + use<> {
self.dispatcher.as_test().unwrap().simulate_random_delay()
}

View file

@ -438,14 +438,8 @@ mod tests {
actions!(
test,
[
A,
B,
C,
D,
E,
F,
G, // Don't wrap, test the trailing comma
]
A, B, C, D, E, F, G, // Don't wrap, test the trailing comma
]
);
}
}

View file

@ -398,8 +398,12 @@ impl BladeRenderer {
log::error!("GPU hung");
#[cfg(target_os = "linux")]
if self.gpu.device_information().driver_name == "radv" {
log::error!("there's a known bug with amdgpu/radv, try setting ZED_PATH_SAMPLE_COUNT=0 as a workaround");
log::error!("if that helps you're running into https://github.com/zed-industries/zed/issues/26143");
log::error!(
"there's a known bug with amdgpu/radv, try setting ZED_PATH_SAMPLE_COUNT=0 as a workaround"
);
log::error!(
"if that helps you're running into https://github.com/zed-industries/zed/issues/26143"
);
}
log::error!(
"your device information is: {:?}",

View file

@ -632,7 +632,7 @@ pub(super) fn get_xkb_compose_state(cx: &xkb::Context) -> Option<xkb::compose::S
#[cfg(any(feature = "wayland", feature = "x11"))]
pub(super) unsafe fn read_fd(mut fd: filedescriptor::FileDescriptor) -> Result<Vec<u8>> {
let mut file = File::from_raw_fd(fd.as_raw_fd());
let mut file = unsafe { File::from_raw_fd(fd.as_raw_fd()) };
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
Ok(buffer)

View file

@ -256,7 +256,7 @@ impl Clipboard {
}
Ok(n) => written += n,
Err(err) if err.kind() == ErrorKind::WouldBlock => {
break Ok(PostAction::Continue)
break Ok(PostAction::Continue);
}
Err(_) => break Ok(PostAction::Remove),
}

View file

@ -186,12 +186,15 @@ fn find_visuals(xcb: &XCBConnection, screen_index: usize) -> VisualSet {
colormap: 0,
depth: depth_info.depth,
};
log::debug!("Visual id: {}, class: {:?}, depth: {}, bits_per_value: {}, masks: 0x{:x} 0x{:x} 0x{:x}",
log::debug!(
"Visual id: {}, class: {:?}, depth: {}, bits_per_value: {}, masks: 0x{:x} 0x{:x} 0x{:x}",
visual_type.visual_id,
visual_type.class,
depth_info.depth,
visual_type.bits_per_rgb_value,
visual_type.red_mask, visual_type.green_mask, visual_type.blue_mask,
visual_type.red_mask,
visual_type.green_mask,
visual_type.blue_mask,
);
if (
@ -409,15 +412,27 @@ impl X11WindowState {
let mut bounds = params.bounds.to_device_pixels(scale_factor);
if bounds.size.width.0 == 0 || bounds.size.height.0 == 0 {
log::warn!("Window bounds contain a zero value. height={}, width={}. Falling back to defaults.", bounds.size.height.0, bounds.size.width.0);
log::warn!(
"Window bounds contain a zero value. height={}, width={}. Falling back to defaults.",
bounds.size.height.0,
bounds.size.width.0
);
bounds.size.width = 800.into();
bounds.size.height = 600.into();
}
check_reply(
|| {
format!("X11 CreateWindow failed. depth: {}, x_window: {}, visual_set.root: {}, bounds.origin.x.0: {}, bounds.origin.y.0: {}, bounds.size.width.0: {}, bounds.size.height.0: {}",
visual.depth, x_window, visual_set.root, bounds.origin.x.0 + 2, bounds.origin.y.0, bounds.size.width.0, bounds.size.height.0)
format!(
"X11 CreateWindow failed. depth: {}, x_window: {}, visual_set.root: {}, bounds.origin.x.0: {}, bounds.origin.y.0: {}, bounds.size.width.0: {}, bounds.size.height.0: {}",
visual.depth,
x_window,
visual_set.root,
bounds.origin.x.0 + 2,
bounds.origin.y.0,
bounds.size.width.0,
bounds.size.height.0
)
},
xcb.create_window(
visual.depth,

View file

@ -74,11 +74,13 @@ trait NSStringExt {
impl NSStringExt for id {
unsafe fn to_str(&self) -> &str {
let cstr = self.UTF8String();
if cstr.is_null() {
""
} else {
CStr::from_ptr(cstr as *mut c_char).to_str().unwrap()
unsafe {
let cstr = self.UTF8String();
if cstr.is_null() {
""
} else {
CStr::from_ptr(cstr as *mut c_char).to_str().unwrap()
}
}
}
}
@ -134,7 +136,7 @@ unsafe impl objc::Encode for NSRange {
}
unsafe fn ns_string(string: &str) -> id {
NSString::alloc(nil).init_str(string).autorelease()
unsafe { NSString::alloc(nil).init_str(string).autorelease() }
}
impl From<NSSize> for Size<Pixels> {

View file

@ -65,7 +65,7 @@ impl MacDisplay {
}
#[link(name = "ApplicationServices", kind = "framework")]
extern "C" {
unsafe extern "C" {
fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef;
}

View file

@ -30,9 +30,11 @@ impl DisplayLink {
_flags_out: *mut i64,
frame_requests: *mut c_void,
) -> i32 {
let frame_requests = frame_requests as dispatch_source_t;
dispatch_source_merge_data(frame_requests, 1);
0
unsafe {
let frame_requests = frame_requests as dispatch_source_t;
dispatch_source_merge_data(frame_requests, 1);
0
}
}
unsafe {
@ -202,7 +204,7 @@ mod sys {
#[link(name = "CoreFoundation", kind = "framework")]
#[link(name = "CoreVideo", kind = "framework")]
#[allow(improper_ctypes, unknown_lints, clippy::duplicated_attributes)]
extern "C" {
unsafe extern "C" {
pub fn CVDisplayLinkCreateWithActiveCGDisplays(
display_link_out: *mut *mut CVDisplayLink,
) -> i32;
@ -228,40 +230,46 @@ mod sys {
callback: CVDisplayLinkOutputCallback,
user_info: *mut c_void,
) -> Result<Self> {
let mut display_link: *mut CVDisplayLink = 0 as _;
unsafe {
let mut display_link: *mut CVDisplayLink = 0 as _;
let code = CVDisplayLinkCreateWithActiveCGDisplays(&mut display_link);
anyhow::ensure!(code == 0, "could not create display link, code: {}", code);
let code = CVDisplayLinkCreateWithActiveCGDisplays(&mut display_link);
anyhow::ensure!(code == 0, "could not create display link, code: {}", code);
let mut display_link = DisplayLink::from_ptr(display_link);
let mut display_link = DisplayLink::from_ptr(display_link);
let code = CVDisplayLinkSetOutputCallback(&mut display_link, callback, user_info);
anyhow::ensure!(code == 0, "could not set output callback, code: {}", code);
let code = CVDisplayLinkSetOutputCallback(&mut display_link, callback, user_info);
anyhow::ensure!(code == 0, "could not set output callback, code: {}", code);
let code = CVDisplayLinkSetCurrentCGDisplay(&mut display_link, display_id);
anyhow::ensure!(
code == 0,
"could not assign display to display link, code: {}",
code
);
let code = CVDisplayLinkSetCurrentCGDisplay(&mut display_link, display_id);
anyhow::ensure!(
code == 0,
"could not assign display to display link, code: {}",
code
);
Ok(display_link)
Ok(display_link)
}
}
}
impl DisplayLinkRef {
/// Apple docs: [CVDisplayLinkStart](https://developer.apple.com/documentation/corevideo/1457193-cvdisplaylinkstart?language=objc)
pub unsafe fn start(&mut self) -> Result<()> {
let code = CVDisplayLinkStart(self);
anyhow::ensure!(code == 0, "could not start display link, code: {}", code);
Ok(())
unsafe {
let code = CVDisplayLinkStart(self);
anyhow::ensure!(code == 0, "could not start display link, code: {}", code);
Ok(())
}
}
/// Apple docs: [CVDisplayLinkStop](https://developer.apple.com/documentation/corevideo/1457281-cvdisplaylinkstop?language=objc)
pub unsafe fn stop(&mut self) -> Result<()> {
let code = CVDisplayLinkStop(self);
anyhow::ensure!(code == 0, "could not stop display link, code: {}", code);
Ok(())
unsafe {
let code = CVDisplayLinkStop(self);
anyhow::ensure!(code == 0, "could not stop display link, code: {}", code);
Ok(())
}
}
}
}

View file

@ -80,19 +80,21 @@ pub fn key_to_native(key: &str) -> Cow<str> {
}
unsafe fn read_modifiers(native_event: id) -> Modifiers {
let modifiers = native_event.modifierFlags();
let control = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
let shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
let command = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask);
unsafe {
let modifiers = native_event.modifierFlags();
let control = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
let shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
let command = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask);
Modifiers {
control,
alt,
shift,
platform: command,
function,
Modifiers {
control,
alt,
shift,
platform: command,
function,
}
}
}
@ -101,344 +103,351 @@ impl PlatformInput {
native_event: id,
window_height: Option<Pixels>,
) -> Option<Self> {
let event_type = native_event.eventType();
unsafe {
let event_type = native_event.eventType();
// Filter out event types that aren't in the NSEventType enum.
// See https://github.com/servo/cocoa-rs/issues/155#issuecomment-323482792 for details.
match event_type as u64 {
0 | 21 | 32 | 33 | 35 | 36 | 37 => {
return None;
// Filter out event types that aren't in the NSEventType enum.
// See https://github.com/servo/cocoa-rs/issues/155#issuecomment-323482792 for details.
match event_type as u64 {
0 | 21 | 32 | 33 | 35 | 36 | 37 => {
return None;
}
_ => {}
}
_ => {}
}
match event_type {
NSEventType::NSFlagsChanged => Some(Self::ModifiersChanged(ModifiersChangedEvent {
modifiers: read_modifiers(native_event),
})),
NSEventType::NSKeyDown => Some(Self::KeyDown(KeyDownEvent {
keystroke: parse_keystroke(native_event),
is_held: native_event.isARepeat() == YES,
})),
NSEventType::NSKeyUp => Some(Self::KeyUp(KeyUpEvent {
keystroke: parse_keystroke(native_event),
})),
NSEventType::NSLeftMouseDown
| NSEventType::NSRightMouseDown
| NSEventType::NSOtherMouseDown => {
let button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
window_height.map(|window_height| {
Self::MouseDown(MouseDownEvent {
button,
position: point(
px(native_event.locationInWindow().x as f32),
// MacOS screen coordinates are relative to bottom left
window_height - px(native_event.locationInWindow().y as f32),
),
match event_type {
NSEventType::NSFlagsChanged => {
Some(Self::ModifiersChanged(ModifiersChangedEvent {
modifiers: read_modifiers(native_event),
click_count: native_event.clickCount() as usize,
first_mouse: false,
})
})
}
NSEventType::NSLeftMouseUp
| NSEventType::NSRightMouseUp
| NSEventType::NSOtherMouseUp => {
let button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
window_height.map(|window_height| {
Self::MouseUp(MouseUpEvent {
button,
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
click_count: native_event.clickCount() as usize,
})
})
}
// Some mice (like Logitech MX Master) send navigation buttons as swipe events
NSEventType::NSEventTypeSwipe => {
let navigation_direction = match native_event.phase() {
NSEventPhase::NSEventPhaseEnded => match native_event.deltaX() {
x if x > 0.0 => Some(NavigationDirection::Back),
x if x < 0.0 => Some(NavigationDirection::Forward),
}))
}
NSEventType::NSKeyDown => Some(Self::KeyDown(KeyDownEvent {
keystroke: parse_keystroke(native_event),
is_held: native_event.isARepeat() == YES,
})),
NSEventType::NSKeyUp => Some(Self::KeyUp(KeyUpEvent {
keystroke: parse_keystroke(native_event),
})),
NSEventType::NSLeftMouseDown
| NSEventType::NSRightMouseDown
| NSEventType::NSOtherMouseDown => {
let button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
},
_ => return None,
};
match navigation_direction {
Some(direction) => window_height.map(|window_height| {
};
window_height.map(|window_height| {
Self::MouseDown(MouseDownEvent {
button: MouseButton::Navigate(direction),
button,
position: point(
px(native_event.locationInWindow().x as f32),
// MacOS screen coordinates are relative to bottom left
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
click_count: native_event.clickCount() as usize,
first_mouse: false,
})
})
}
NSEventType::NSLeftMouseUp
| NSEventType::NSRightMouseUp
| NSEventType::NSOtherMouseUp => {
let button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
window_height.map(|window_height| {
Self::MouseUp(MouseUpEvent {
button,
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
click_count: 1,
first_mouse: false,
click_count: native_event.clickCount() as usize,
})
}),
_ => None,
})
}
}
NSEventType::NSScrollWheel => window_height.map(|window_height| {
let phase = match native_event.phase() {
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => {
TouchPhase::Started
// Some mice (like Logitech MX Master) send navigation buttons as swipe events
NSEventType::NSEventTypeSwipe => {
let navigation_direction = match native_event.phase() {
NSEventPhase::NSEventPhaseEnded => match native_event.deltaX() {
x if x > 0.0 => Some(NavigationDirection::Back),
x if x < 0.0 => Some(NavigationDirection::Forward),
_ => return None,
},
_ => return None,
};
match navigation_direction {
Some(direction) => window_height.map(|window_height| {
Self::MouseDown(MouseDownEvent {
button: MouseButton::Navigate(direction),
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
click_count: 1,
first_mouse: false,
})
}),
_ => None,
}
NSEventPhase::NSEventPhaseEnded => TouchPhase::Ended,
_ => TouchPhase::Moved,
};
}
NSEventType::NSScrollWheel => window_height.map(|window_height| {
let phase = match native_event.phase() {
NSEventPhase::NSEventPhaseMayBegin | NSEventPhase::NSEventPhaseBegan => {
TouchPhase::Started
}
NSEventPhase::NSEventPhaseEnded => TouchPhase::Ended,
_ => TouchPhase::Moved,
};
let raw_data = point(
native_event.scrollingDeltaX() as f32,
native_event.scrollingDeltaY() as f32,
);
let raw_data = point(
native_event.scrollingDeltaX() as f32,
native_event.scrollingDeltaY() as f32,
);
let delta = if native_event.hasPreciseScrollingDeltas() == YES {
ScrollDelta::Pixels(raw_data.map(px))
} else {
ScrollDelta::Lines(raw_data)
};
let delta = if native_event.hasPreciseScrollingDeltas() == YES {
ScrollDelta::Pixels(raw_data.map(px))
} else {
ScrollDelta::Lines(raw_data)
};
Self::ScrollWheel(ScrollWheelEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
delta,
touch_phase: phase,
modifiers: read_modifiers(native_event),
})
}),
NSEventType::NSLeftMouseDragged
| NSEventType::NSRightMouseDragged
| NSEventType::NSOtherMouseDragged => {
let pressed_button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
window_height.map(|window_height| {
Self::MouseMove(MouseMoveEvent {
pressed_button: Some(pressed_button),
Self::ScrollWheel(ScrollWheelEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
delta,
touch_phase: phase,
modifiers: read_modifiers(native_event),
})
})
}
NSEventType::NSMouseMoved => window_height.map(|window_height| {
Self::MouseMove(MouseMoveEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
pressed_button: None,
modifiers: read_modifiers(native_event),
})
}),
NSEventType::NSMouseExited => window_height.map(|window_height| {
Self::MouseExited(MouseExitEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
}),
NSEventType::NSLeftMouseDragged
| NSEventType::NSRightMouseDragged
| NSEventType::NSOtherMouseDragged => {
let pressed_button = match native_event.buttonNumber() {
0 => MouseButton::Left,
1 => MouseButton::Right,
2 => MouseButton::Middle,
3 => MouseButton::Navigate(NavigationDirection::Back),
4 => MouseButton::Navigate(NavigationDirection::Forward),
// Other mouse buttons aren't tracked currently
_ => return None,
};
pressed_button: None,
modifiers: read_modifiers(native_event),
})
}),
_ => None,
window_height.map(|window_height| {
Self::MouseMove(MouseMoveEvent {
pressed_button: Some(pressed_button),
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
modifiers: read_modifiers(native_event),
})
})
}
NSEventType::NSMouseMoved => window_height.map(|window_height| {
Self::MouseMove(MouseMoveEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
pressed_button: None,
modifiers: read_modifiers(native_event),
})
}),
NSEventType::NSMouseExited => window_height.map(|window_height| {
Self::MouseExited(MouseExitEvent {
position: point(
px(native_event.locationInWindow().x as f32),
window_height - px(native_event.locationInWindow().y as f32),
),
pressed_button: None,
modifiers: read_modifiers(native_event),
})
}),
_ => None,
}
}
}
}
unsafe fn parse_keystroke(native_event: id) -> Keystroke {
use cocoa::appkit::*;
unsafe {
use cocoa::appkit::*;
let mut characters = native_event
.charactersIgnoringModifiers()
.to_str()
.to_string();
let mut key_char = None;
let first_char = characters.chars().next().map(|ch| ch as u16);
let modifiers = native_event.modifierFlags();
let mut characters = native_event
.charactersIgnoringModifiers()
.to_str()
.to_string();
let mut key_char = None;
let first_char = characters.chars().next().map(|ch| ch as u16);
let modifiers = native_event.modifierFlags();
let control = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
let mut shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
let command = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask)
&& first_char.map_or(true, |ch| {
!(NSUpArrowFunctionKey..=NSModeSwitchFunctionKey).contains(&ch)
});
let control = modifiers.contains(NSEventModifierFlags::NSControlKeyMask);
let alt = modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask);
let mut shift = modifiers.contains(NSEventModifierFlags::NSShiftKeyMask);
let command = modifiers.contains(NSEventModifierFlags::NSCommandKeyMask);
let function = modifiers.contains(NSEventModifierFlags::NSFunctionKeyMask)
&& first_char.map_or(true, |ch| {
!(NSUpArrowFunctionKey..=NSModeSwitchFunctionKey).contains(&ch)
});
#[allow(non_upper_case_globals)]
let key = match first_char {
Some(SPACE_KEY) => {
key_char = Some(" ".to_string());
"space".to_string()
}
Some(TAB_KEY) => {
key_char = Some("\t".to_string());
"tab".to_string()
}
Some(ENTER_KEY) | Some(NUMPAD_ENTER_KEY) => {
key_char = Some("\n".to_string());
"enter".to_string()
}
Some(BACKSPACE_KEY) => "backspace".to_string(),
Some(ESCAPE_KEY) => "escape".to_string(),
Some(SHIFT_TAB_KEY) => "tab".to_string(),
Some(NSUpArrowFunctionKey) => "up".to_string(),
Some(NSDownArrowFunctionKey) => "down".to_string(),
Some(NSLeftArrowFunctionKey) => "left".to_string(),
Some(NSRightArrowFunctionKey) => "right".to_string(),
Some(NSPageUpFunctionKey) => "pageup".to_string(),
Some(NSPageDownFunctionKey) => "pagedown".to_string(),
Some(NSHomeFunctionKey) => "home".to_string(),
Some(NSEndFunctionKey) => "end".to_string(),
Some(NSDeleteFunctionKey) => "delete".to_string(),
// Observed Insert==NSHelpFunctionKey not NSInsertFunctionKey.
Some(NSHelpFunctionKey) => "insert".to_string(),
Some(NSF1FunctionKey) => "f1".to_string(),
Some(NSF2FunctionKey) => "f2".to_string(),
Some(NSF3FunctionKey) => "f3".to_string(),
Some(NSF4FunctionKey) => "f4".to_string(),
Some(NSF5FunctionKey) => "f5".to_string(),
Some(NSF6FunctionKey) => "f6".to_string(),
Some(NSF7FunctionKey) => "f7".to_string(),
Some(NSF8FunctionKey) => "f8".to_string(),
Some(NSF9FunctionKey) => "f9".to_string(),
Some(NSF10FunctionKey) => "f10".to_string(),
Some(NSF11FunctionKey) => "f11".to_string(),
Some(NSF12FunctionKey) => "f12".to_string(),
Some(NSF13FunctionKey) => "f13".to_string(),
Some(NSF14FunctionKey) => "f14".to_string(),
Some(NSF15FunctionKey) => "f15".to_string(),
Some(NSF16FunctionKey) => "f16".to_string(),
Some(NSF17FunctionKey) => "f17".to_string(),
Some(NSF18FunctionKey) => "f18".to_string(),
Some(NSF19FunctionKey) => "f19".to_string(),
Some(NSF20FunctionKey) => "f20".to_string(),
Some(NSF21FunctionKey) => "f21".to_string(),
Some(NSF22FunctionKey) => "f22".to_string(),
Some(NSF23FunctionKey) => "f23".to_string(),
Some(NSF24FunctionKey) => "f24".to_string(),
Some(NSF25FunctionKey) => "f25".to_string(),
Some(NSF26FunctionKey) => "f26".to_string(),
Some(NSF27FunctionKey) => "f27".to_string(),
Some(NSF28FunctionKey) => "f28".to_string(),
Some(NSF29FunctionKey) => "f29".to_string(),
Some(NSF30FunctionKey) => "f30".to_string(),
Some(NSF31FunctionKey) => "f31".to_string(),
Some(NSF32FunctionKey) => "f32".to_string(),
Some(NSF33FunctionKey) => "f33".to_string(),
Some(NSF34FunctionKey) => "f34".to_string(),
Some(NSF35FunctionKey) => "f35".to_string(),
_ => {
// Cases to test when modifying this:
//
// qwerty key | none | cmd | cmd-shift
// * Armenian s | ս | cmd-s | cmd-shift-s (layout is non-ASCII, so we use cmd layout)
// * Dvorak+QWERTY s | o | cmd-s | cmd-shift-s (layout switches on cmd)
// * Ukrainian+QWERTY s | с | cmd-s | cmd-shift-s (macOS reports cmd-s instead of cmd-S)
// * Czech 7 | ý | cmd-ý | cmd-7 (layout has shifted numbers)
// * Norwegian 7 | 7 | cmd-7 | cmd-/ (macOS reports cmd-shift-7 instead of cmd-/)
// * Russian 7 | 7 | cmd-7 | cmd-& (shift-7 is . but when cmd is down, should use cmd layout)
// * German QWERTZ ; | ö | cmd-ö | cmd-Ö (Zed's shift special case only applies to a-z)
//
let mut chars_ignoring_modifiers =
chars_for_modified_key(native_event.keyCode(), NO_MOD);
let mut chars_with_shift = chars_for_modified_key(native_event.keyCode(), SHIFT_MOD);
let always_use_cmd_layout = always_use_command_layout();
// Handle Dvorak+QWERTY / Russian / Armenian
if command || always_use_cmd_layout {
let chars_with_cmd = chars_for_modified_key(native_event.keyCode(), CMD_MOD);
let chars_with_both =
chars_for_modified_key(native_event.keyCode(), CMD_MOD | SHIFT_MOD);
// We don't do this in the case that the shifted command key generates
// the same character as the unshifted command key (Norwegian, e.g.)
if chars_with_both != chars_with_cmd {
chars_with_shift = chars_with_both;
// Handle edge-case where cmd-shift-s reports cmd-s instead of
// cmd-shift-s (Ukrainian, etc.)
} else if chars_with_cmd.to_ascii_uppercase() != chars_with_cmd {
chars_with_shift = chars_with_cmd.to_ascii_uppercase();
}
chars_ignoring_modifiers = chars_with_cmd;
#[allow(non_upper_case_globals)]
let key = match first_char {
Some(SPACE_KEY) => {
key_char = Some(" ".to_string());
"space".to_string()
}
if !control && !command && !function {
let mut mods = NO_MOD;
if shift {
mods |= SHIFT_MOD;
}
if alt {
mods |= OPTION_MOD;
}
key_char = Some(chars_for_modified_key(native_event.keyCode(), mods));
Some(TAB_KEY) => {
key_char = Some("\t".to_string());
"tab".to_string()
}
Some(ENTER_KEY) | Some(NUMPAD_ENTER_KEY) => {
key_char = Some("\n".to_string());
"enter".to_string()
}
Some(BACKSPACE_KEY) => "backspace".to_string(),
Some(ESCAPE_KEY) => "escape".to_string(),
Some(SHIFT_TAB_KEY) => "tab".to_string(),
Some(NSUpArrowFunctionKey) => "up".to_string(),
Some(NSDownArrowFunctionKey) => "down".to_string(),
Some(NSLeftArrowFunctionKey) => "left".to_string(),
Some(NSRightArrowFunctionKey) => "right".to_string(),
Some(NSPageUpFunctionKey) => "pageup".to_string(),
Some(NSPageDownFunctionKey) => "pagedown".to_string(),
Some(NSHomeFunctionKey) => "home".to_string(),
Some(NSEndFunctionKey) => "end".to_string(),
Some(NSDeleteFunctionKey) => "delete".to_string(),
// Observed Insert==NSHelpFunctionKey not NSInsertFunctionKey.
Some(NSHelpFunctionKey) => "insert".to_string(),
Some(NSF1FunctionKey) => "f1".to_string(),
Some(NSF2FunctionKey) => "f2".to_string(),
Some(NSF3FunctionKey) => "f3".to_string(),
Some(NSF4FunctionKey) => "f4".to_string(),
Some(NSF5FunctionKey) => "f5".to_string(),
Some(NSF6FunctionKey) => "f6".to_string(),
Some(NSF7FunctionKey) => "f7".to_string(),
Some(NSF8FunctionKey) => "f8".to_string(),
Some(NSF9FunctionKey) => "f9".to_string(),
Some(NSF10FunctionKey) => "f10".to_string(),
Some(NSF11FunctionKey) => "f11".to_string(),
Some(NSF12FunctionKey) => "f12".to_string(),
Some(NSF13FunctionKey) => "f13".to_string(),
Some(NSF14FunctionKey) => "f14".to_string(),
Some(NSF15FunctionKey) => "f15".to_string(),
Some(NSF16FunctionKey) => "f16".to_string(),
Some(NSF17FunctionKey) => "f17".to_string(),
Some(NSF18FunctionKey) => "f18".to_string(),
Some(NSF19FunctionKey) => "f19".to_string(),
Some(NSF20FunctionKey) => "f20".to_string(),
Some(NSF21FunctionKey) => "f21".to_string(),
Some(NSF22FunctionKey) => "f22".to_string(),
Some(NSF23FunctionKey) => "f23".to_string(),
Some(NSF24FunctionKey) => "f24".to_string(),
Some(NSF25FunctionKey) => "f25".to_string(),
Some(NSF26FunctionKey) => "f26".to_string(),
Some(NSF27FunctionKey) => "f27".to_string(),
Some(NSF28FunctionKey) => "f28".to_string(),
Some(NSF29FunctionKey) => "f29".to_string(),
Some(NSF30FunctionKey) => "f30".to_string(),
Some(NSF31FunctionKey) => "f31".to_string(),
Some(NSF32FunctionKey) => "f32".to_string(),
Some(NSF33FunctionKey) => "f33".to_string(),
Some(NSF34FunctionKey) => "f34".to_string(),
Some(NSF35FunctionKey) => "f35".to_string(),
_ => {
// Cases to test when modifying this:
//
// qwerty key | none | cmd | cmd-shift
// * Armenian s | ս | cmd-s | cmd-shift-s (layout is non-ASCII, so we use cmd layout)
// * Dvorak+QWERTY s | o | cmd-s | cmd-shift-s (layout switches on cmd)
// * Ukrainian+QWERTY s | с | cmd-s | cmd-shift-s (macOS reports cmd-s instead of cmd-S)
// * Czech 7 | ý | cmd-ý | cmd-7 (layout has shifted numbers)
// * Norwegian 7 | 7 | cmd-7 | cmd-/ (macOS reports cmd-shift-7 instead of cmd-/)
// * Russian 7 | 7 | cmd-7 | cmd-& (shift-7 is . but when cmd is down, should use cmd layout)
// * German QWERTZ ; | ö | cmd-ö | cmd-Ö (Zed's shift special case only applies to a-z)
//
let mut chars_ignoring_modifiers =
chars_for_modified_key(native_event.keyCode(), NO_MOD);
let mut chars_with_shift =
chars_for_modified_key(native_event.keyCode(), SHIFT_MOD);
let always_use_cmd_layout = always_use_command_layout();
let mut key = if shift
&& chars_ignoring_modifiers
.chars()
.all(|c| c.is_ascii_lowercase())
{
chars_ignoring_modifiers
} else if shift {
shift = false;
chars_with_shift
} else {
chars_ignoring_modifiers
};
// Handle Dvorak+QWERTY / Russian / Armenian
if command || always_use_cmd_layout {
let chars_with_cmd = chars_for_modified_key(native_event.keyCode(), CMD_MOD);
let chars_with_both =
chars_for_modified_key(native_event.keyCode(), CMD_MOD | SHIFT_MOD);
key
// We don't do this in the case that the shifted command key generates
// the same character as the unshifted command key (Norwegian, e.g.)
if chars_with_both != chars_with_cmd {
chars_with_shift = chars_with_both;
// Handle edge-case where cmd-shift-s reports cmd-s instead of
// cmd-shift-s (Ukrainian, etc.)
} else if chars_with_cmd.to_ascii_uppercase() != chars_with_cmd {
chars_with_shift = chars_with_cmd.to_ascii_uppercase();
}
chars_ignoring_modifiers = chars_with_cmd;
}
if !control && !command && !function {
let mut mods = NO_MOD;
if shift {
mods |= SHIFT_MOD;
}
if alt {
mods |= OPTION_MOD;
}
key_char = Some(chars_for_modified_key(native_event.keyCode(), mods));
}
let mut key = if shift
&& chars_ignoring_modifiers
.chars()
.all(|c| c.is_ascii_lowercase())
{
chars_ignoring_modifiers
} else if shift {
shift = false;
chars_with_shift
} else {
chars_ignoring_modifiers
};
key
}
};
Keystroke {
modifiers: Modifiers {
control,
alt,
shift,
platform: command,
function,
},
key,
key_char,
}
};
Keystroke {
modifiers: Modifiers {
control,
alt,
shift,
platform: command,
function,
},
key,
key_char,
}
}

View file

@ -471,7 +471,8 @@ impl MetalRenderer {
if !ok {
command_encoder.end_encoding();
return Err(anyhow!("scene too large: {} paths, {} shadows, {} quads, {} underlines, {} mono, {} poly, {} surfaces",
return Err(anyhow!(
"scene too large: {} paths, {} shadows, {} quads, {} underlines, {} mono, {} poly, {} surfaces",
scene.paths.len(),
scene.shadows.len(),
scene.quads.len(),

View file

@ -132,7 +132,7 @@ fn append_system_fallbacks(fallback_array: CFMutableArrayRef, font_ref: CTFontRe
}
#[link(name = "CoreText", kind = "framework")]
extern "C" {
unsafe extern "C" {
static kCTFontOpenTypeFeatureTag: CFStringRef;
static kCTFontOpenTypeFeatureValue: CFStringRef;

View file

@ -68,79 +68,82 @@ static mut APP_DELEGATE_CLASS: *const Class = ptr::null();
#[ctor]
unsafe fn build_classes() {
APP_CLASS = {
let mut decl = ClassDecl::new("GPUIApplication", class!(NSApplication)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR);
decl.register()
unsafe {
APP_CLASS = {
let mut decl = ClassDecl::new("GPUIApplication", class!(NSApplication)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR);
decl.register()
}
};
unsafe {
APP_DELEGATE_CLASS = unsafe {
let mut decl = ClassDecl::new("GPUIApplicationDelegate", class!(NSResponder)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR);
decl.add_method(
sel!(applicationDidFinishLaunching:),
did_finish_launching as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
should_handle_reopen as extern "C" fn(&mut Object, Sel, id, bool),
);
decl.add_method(
sel!(applicationWillTerminate:),
will_terminate as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(handleGPUIMenuItem:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
// Add menu item handlers so that OS save panels have the correct key commands
decl.add_method(
sel!(cut:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(copy:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(paste:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(selectAll:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(undo:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(redo:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(validateMenuItem:),
validate_menu_item as extern "C" fn(&mut Object, Sel, id) -> bool,
);
decl.add_method(
sel!(menuWillOpen:),
menu_will_open as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(applicationDockMenu:),
handle_dock_menu as extern "C" fn(&mut Object, Sel, id) -> id,
);
decl.add_method(
sel!(application:openURLs:),
open_urls as extern "C" fn(&mut Object, Sel, id, id),
);
APP_DELEGATE_CLASS = {
let mut decl = ClassDecl::new("GPUIApplicationDelegate", class!(NSResponder)).unwrap();
decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR);
decl.add_method(
sel!(applicationDidFinishLaunching:),
did_finish_launching as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(applicationShouldHandleReopen:hasVisibleWindows:),
should_handle_reopen as extern "C" fn(&mut Object, Sel, id, bool),
);
decl.add_method(
sel!(applicationWillTerminate:),
will_terminate as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(handleGPUIMenuItem:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
// Add menu item handlers so that OS save panels have the correct key commands
decl.add_method(
sel!(cut:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(copy:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(paste:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(selectAll:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(undo:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(redo:),
handle_menu_item as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(validateMenuItem:),
validate_menu_item as extern "C" fn(&mut Object, Sel, id) -> bool,
);
decl.add_method(
sel!(menuWillOpen:),
menu_will_open as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(applicationDockMenu:),
handle_dock_menu as extern "C" fn(&mut Object, Sel, id) -> id,
);
decl.add_method(
sel!(application:openURLs:),
open_urls as extern "C" fn(&mut Object, Sel, id, id),
);
decl.add_method(
sel!(onKeyboardLayoutChange:),
on_keyboard_layout_change as extern "C" fn(&mut Object, Sel, id),
);
decl.add_method(
sel!(onKeyboardLayoutChange:),
on_keyboard_layout_change as extern "C" fn(&mut Object, Sel, id),
);
decl.register()
decl.register()
}
}
}
@ -206,14 +209,16 @@ impl MacPlatform {
}
unsafe fn read_from_pasteboard(&self, pasteboard: *mut Object, kind: id) -> Option<&[u8]> {
let data = pasteboard.dataForType(kind);
if data == nil {
None
} else {
Some(slice::from_raw_parts(
data.bytes() as *mut u8,
data.length() as usize,
))
unsafe {
let data = pasteboard.dataForType(kind);
if data == nil {
None
} else {
Some(slice::from_raw_parts(
data.bytes() as *mut u8,
data.length() as usize,
))
}
}
}
@ -224,36 +229,38 @@ impl MacPlatform {
actions: &mut Vec<Box<dyn Action>>,
keymap: &Keymap,
) -> id {
let application_menu = NSMenu::new(nil).autorelease();
application_menu.setDelegate_(delegate);
unsafe {
let application_menu = NSMenu::new(nil).autorelease();
application_menu.setDelegate_(delegate);
for menu_config in menus {
let menu = NSMenu::new(nil).autorelease();
let menu_title = ns_string(&menu_config.name);
menu.setTitle_(menu_title);
menu.setDelegate_(delegate);
for menu_config in menus {
let menu = NSMenu::new(nil).autorelease();
let menu_title = ns_string(&menu_config.name);
menu.setTitle_(menu_title);
menu.setDelegate_(delegate);
for item_config in menu_config.items {
menu.addItem_(Self::create_menu_item(
item_config,
delegate,
actions,
keymap,
));
for item_config in menu_config.items {
menu.addItem_(Self::create_menu_item(
item_config,
delegate,
actions,
keymap,
));
}
let menu_item = NSMenuItem::new(nil).autorelease();
menu_item.setTitle_(menu_title);
menu_item.setSubmenu_(menu);
application_menu.addItem_(menu_item);
if menu_config.name == "Window" {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setWindowsMenu_(menu);
}
}
let menu_item = NSMenuItem::new(nil).autorelease();
menu_item.setTitle_(menu_title);
menu_item.setSubmenu_(menu);
application_menu.addItem_(menu_item);
if menu_config.name == "Window" {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setWindowsMenu_(menu);
}
application_menu
}
application_menu
}
unsafe fn create_dock_menu(
@ -263,18 +270,20 @@ impl MacPlatform {
actions: &mut Vec<Box<dyn Action>>,
keymap: &Keymap,
) -> id {
let dock_menu = NSMenu::new(nil);
dock_menu.setDelegate_(delegate);
for item_config in menu_items {
dock_menu.addItem_(Self::create_menu_item(
item_config,
delegate,
actions,
keymap,
));
}
unsafe {
let dock_menu = NSMenu::new(nil);
dock_menu.setDelegate_(delegate);
for item_config in menu_items {
dock_menu.addItem_(Self::create_menu_item(
item_config,
delegate,
actions,
keymap,
));
}
dock_menu
dock_menu
}
}
unsafe fn create_menu_item(
@ -283,70 +292,80 @@ impl MacPlatform {
actions: &mut Vec<Box<dyn Action>>,
keymap: &Keymap,
) -> id {
match item {
MenuItem::Separator => NSMenuItem::separatorItem(nil),
MenuItem::Action {
name,
action,
os_action,
} => {
let keystrokes = crate::Keymap::binding_to_display_from_bindings_iterator(
keymap.bindings_for_action(action.as_ref()),
)
.map(|binding| binding.keystrokes());
unsafe {
match item {
MenuItem::Separator => NSMenuItem::separatorItem(nil),
MenuItem::Action {
name,
action,
os_action,
} => {
let keystrokes = crate::Keymap::binding_to_display_from_bindings_iterator(
keymap.bindings_for_action(action.as_ref()),
)
.map(|binding| binding.keystrokes());
let selector = match os_action {
Some(crate::OsAction::Cut) => selector("cut:"),
Some(crate::OsAction::Copy) => selector("copy:"),
Some(crate::OsAction::Paste) => selector("paste:"),
Some(crate::OsAction::SelectAll) => selector("selectAll:"),
// "undo:" and "redo:" are always disabled in our case, as
// we don't have a NSTextView/NSTextField to enable them on.
Some(crate::OsAction::Undo) => selector("handleGPUIMenuItem:"),
Some(crate::OsAction::Redo) => selector("handleGPUIMenuItem:"),
None => selector("handleGPUIMenuItem:"),
};
let selector = match os_action {
Some(crate::OsAction::Cut) => selector("cut:"),
Some(crate::OsAction::Copy) => selector("copy:"),
Some(crate::OsAction::Paste) => selector("paste:"),
Some(crate::OsAction::SelectAll) => selector("selectAll:"),
// "undo:" and "redo:" are always disabled in our case, as
// we don't have a NSTextView/NSTextField to enable them on.
Some(crate::OsAction::Undo) => selector("handleGPUIMenuItem:"),
Some(crate::OsAction::Redo) => selector("handleGPUIMenuItem:"),
None => selector("handleGPUIMenuItem:"),
};
let item;
if let Some(keystrokes) = keystrokes {
if keystrokes.len() == 1 {
let keystroke = &keystrokes[0];
let mut mask = NSEventModifierFlags::empty();
for (modifier, flag) in &[
(
keystroke.modifiers.platform,
NSEventModifierFlags::NSCommandKeyMask,
),
(
keystroke.modifiers.control,
NSEventModifierFlags::NSControlKeyMask,
),
(
keystroke.modifiers.alt,
NSEventModifierFlags::NSAlternateKeyMask,
),
(
keystroke.modifiers.shift,
NSEventModifierFlags::NSShiftKeyMask,
),
] {
if *modifier {
mask |= *flag;
let item;
if let Some(keystrokes) = keystrokes {
if keystrokes.len() == 1 {
let keystroke = &keystrokes[0];
let mut mask = NSEventModifierFlags::empty();
for (modifier, flag) in &[
(
keystroke.modifiers.platform,
NSEventModifierFlags::NSCommandKeyMask,
),
(
keystroke.modifiers.control,
NSEventModifierFlags::NSControlKeyMask,
),
(
keystroke.modifiers.alt,
NSEventModifierFlags::NSAlternateKeyMask,
),
(
keystroke.modifiers.shift,
NSEventModifierFlags::NSShiftKeyMask,
),
] {
if *modifier {
mask |= *flag;
}
}
}
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
ns_string(&name),
selector,
ns_string(key_to_native(&keystroke.key).as_ref()),
)
.autorelease();
if MacPlatform::os_version().unwrap() >= SemanticVersion::new(12, 0, 0) {
let _: () =
msg_send![item, setAllowsAutomaticKeyEquivalentLocalization: NO];
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
ns_string(&name),
selector,
ns_string(key_to_native(&keystroke.key).as_ref()),
)
.autorelease();
if MacPlatform::os_version().unwrap() >= SemanticVersion::new(12, 0, 0)
{
let _: () = msg_send![item, setAllowsAutomaticKeyEquivalentLocalization: NO];
}
item.setKeyEquivalentModifierMask_(mask);
} else {
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
ns_string(&name),
selector,
ns_string(""),
)
.autorelease();
}
item.setKeyEquivalentModifierMask_(mask);
} else {
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
@ -356,36 +375,28 @@ impl MacPlatform {
)
.autorelease();
}
} else {
item = NSMenuItem::alloc(nil)
.initWithTitle_action_keyEquivalent_(
ns_string(&name),
selector,
ns_string(""),
)
.autorelease();
}
let tag = actions.len() as NSInteger;
let _: () = msg_send![item, setTag: tag];
actions.push(action);
item
}
MenuItem::Submenu(Menu { name, items }) => {
let item = NSMenuItem::new(nil).autorelease();
let submenu = NSMenu::new(nil).autorelease();
submenu.setDelegate_(delegate);
for item in items {
submenu.addItem_(Self::create_menu_item(item, delegate, actions, keymap));
}
item.setSubmenu_(submenu);
item.setTitle_(ns_string(&name));
if name == "Services" {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setServicesMenu_(item);
let tag = actions.len() as NSInteger;
let _: () = msg_send![item, setTag: tag];
actions.push(action);
item
}
MenuItem::Submenu(Menu { name, items }) => {
let item = NSMenuItem::new(nil).autorelease();
let submenu = NSMenu::new(nil).autorelease();
submenu.setDelegate_(delegate);
for item in items {
submenu.addItem_(Self::create_menu_item(item, delegate, actions, keymap));
}
item.setSubmenu_(submenu);
item.setTitle_(ns_string(&name));
if name == "Services" {
let app: id = msg_send![APP_CLASS, sharedApplication];
app.setServicesMenu_(item);
}
item
item
}
}
}
}
@ -460,8 +471,10 @@ impl Platform for MacPlatform {
}
unsafe extern "C" fn quit(_: *mut c_void) {
let app = NSApplication::sharedApplication(nil);
let _: () = msg_send![app, terminate: nil];
unsafe {
let app = NSApplication::sharedApplication(nil);
let _: () = msg_send![app, terminate: nil];
}
}
}
@ -1180,75 +1193,81 @@ impl MacPlatform {
state: &MacPlatformState,
text_bytes: &[u8],
) -> ClipboardItem {
let text = String::from_utf8_lossy(text_bytes).to_string();
let metadata = self
.read_from_pasteboard(state.pasteboard, state.text_hash_pasteboard_type)
.and_then(|hash_bytes| {
let hash_bytes = hash_bytes.try_into().ok()?;
let hash = u64::from_be_bytes(hash_bytes);
let metadata =
self.read_from_pasteboard(state.pasteboard, state.metadata_pasteboard_type)?;
unsafe {
let text = String::from_utf8_lossy(text_bytes).to_string();
let metadata = self
.read_from_pasteboard(state.pasteboard, state.text_hash_pasteboard_type)
.and_then(|hash_bytes| {
let hash_bytes = hash_bytes.try_into().ok()?;
let hash = u64::from_be_bytes(hash_bytes);
let metadata = self
.read_from_pasteboard(state.pasteboard, state.metadata_pasteboard_type)?;
if hash == ClipboardString::text_hash(&text) {
String::from_utf8(metadata.to_vec()).ok()
} else {
None
}
});
if hash == ClipboardString::text_hash(&text) {
String::from_utf8(metadata.to_vec()).ok()
} else {
None
}
});
ClipboardItem {
entries: vec![ClipboardEntry::String(ClipboardString { text, metadata })],
ClipboardItem {
entries: vec![ClipboardEntry::String(ClipboardString { text, metadata })],
}
}
}
unsafe fn write_plaintext_to_clipboard(&self, string: &ClipboardString) {
let state = self.0.lock();
state.pasteboard.clearContents();
unsafe {
let state = self.0.lock();
state.pasteboard.clearContents();
let text_bytes = NSData::dataWithBytes_length_(
nil,
string.text.as_ptr() as *const c_void,
string.text.len() as u64,
);
state
.pasteboard
.setData_forType(text_bytes, NSPasteboardTypeString);
if let Some(metadata) = string.metadata.as_ref() {
let hash_bytes = ClipboardString::text_hash(&string.text).to_be_bytes();
let hash_bytes = NSData::dataWithBytes_length_(
let text_bytes = NSData::dataWithBytes_length_(
nil,
hash_bytes.as_ptr() as *const c_void,
hash_bytes.len() as u64,
string.text.as_ptr() as *const c_void,
string.text.len() as u64,
);
state
.pasteboard
.setData_forType(hash_bytes, state.text_hash_pasteboard_type);
.setData_forType(text_bytes, NSPasteboardTypeString);
let metadata_bytes = NSData::dataWithBytes_length_(
nil,
metadata.as_ptr() as *const c_void,
metadata.len() as u64,
);
state
.pasteboard
.setData_forType(metadata_bytes, state.metadata_pasteboard_type);
if let Some(metadata) = string.metadata.as_ref() {
let hash_bytes = ClipboardString::text_hash(&string.text).to_be_bytes();
let hash_bytes = NSData::dataWithBytes_length_(
nil,
hash_bytes.as_ptr() as *const c_void,
hash_bytes.len() as u64,
);
state
.pasteboard
.setData_forType(hash_bytes, state.text_hash_pasteboard_type);
let metadata_bytes = NSData::dataWithBytes_length_(
nil,
metadata.as_ptr() as *const c_void,
metadata.len() as u64,
);
state
.pasteboard
.setData_forType(metadata_bytes, state.metadata_pasteboard_type);
}
}
}
unsafe fn write_image_to_clipboard(&self, image: &Image) {
let state = self.0.lock();
state.pasteboard.clearContents();
unsafe {
let state = self.0.lock();
state.pasteboard.clearContents();
let bytes = NSData::dataWithBytes_length_(
nil,
image.bytes.as_ptr() as *const c_void,
image.bytes.len() as u64,
);
let bytes = NSData::dataWithBytes_length_(
nil,
image.bytes.as_ptr() as *const c_void,
image.bytes.len() as u64,
);
state
.pasteboard
.setData_forType(bytes, Into::<UTType>::into(image.format).inner_mut());
state
.pasteboard
.setData_forType(bytes, Into::<UTType>::into(image.format).inner_mut());
}
}
}
@ -1280,15 +1299,17 @@ fn try_clipboard_image(pasteboard: id, format: ImageFormat) -> Option<ClipboardI
unsafe fn path_from_objc(path: id) -> PathBuf {
let len = msg_send![path, lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
let bytes = path.UTF8String() as *const u8;
let path = str::from_utf8(slice::from_raw_parts(bytes, len)).unwrap();
let bytes = unsafe { path.UTF8String() as *const u8 };
let path = str::from_utf8(unsafe { slice::from_raw_parts(bytes, len) }).unwrap();
PathBuf::from(path)
}
unsafe fn get_mac_platform(object: &mut Object) -> &MacPlatform {
let platform_ptr: *mut c_void = *object.get_ivar(MAC_PLATFORM_IVAR);
assert!(!platform_ptr.is_null());
&*(platform_ptr as *const MacPlatform)
unsafe {
let platform_ptr: *mut c_void = *object.get_ivar(MAC_PLATFORM_IVAR);
assert!(!platform_ptr.is_null());
&*(platform_ptr as *const MacPlatform)
}
}
extern "C" fn did_finish_launching(this: &mut Object, _: Sel, _: id) {
@ -1438,25 +1459,24 @@ extern "C" fn handle_dock_menu(this: &mut Object, _: Sel, _: id) -> id {
}
unsafe fn ns_string(string: &str) -> id {
NSString::alloc(nil).init_str(string).autorelease()
unsafe { NSString::alloc(nil).init_str(string).autorelease() }
}
unsafe fn ns_url_to_path(url: id) -> Result<PathBuf> {
let path: *mut c_char = msg_send![url, fileSystemRepresentation];
if path.is_null() {
Err(anyhow!(
"url is not a file path: {}",
Err(anyhow!("url is not a file path: {}", unsafe {
CStr::from_ptr(url.absoluteString().UTF8String()).to_string_lossy()
))
}))
} else {
Ok(PathBuf::from(OsStr::from_bytes(
CStr::from_ptr(path).to_bytes(),
)))
Ok(PathBuf::from(OsStr::from_bytes(unsafe {
CStr::from_ptr(path).to_bytes()
})))
}
}
#[link(name = "Carbon", kind = "framework")]
extern "C" {
unsafe extern "C" {
pub(super) fn TISCopyCurrentKeyboardLayoutInputSource() -> *mut Object;
pub(super) fn TISGetInputSourceProperty(
inputSource: *mut Object,
@ -1485,7 +1505,7 @@ mod security {
use super::*;
#[link(name = "Security", kind = "framework")]
extern "C" {
unsafe extern "C" {
pub static kSecClass: CFStringRef;
pub static kSecClassInternetPassword: CFStringRef;
pub static kSecAttrServer: CFStringRef;

View file

@ -37,7 +37,7 @@ pub struct MacScreenCaptureStream {
}
#[link(name = "ScreenCaptureKit", kind = "framework")]
extern "C" {}
unsafe extern "C" {}
static mut DELEGATE_CLASS: *const Class = ptr::null();
static mut OUTPUT_CLASS: *const Class = ptr::null();
@ -200,28 +200,31 @@ pub(crate) fn get_sources() -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptur
#[ctor]
unsafe fn build_classes() {
let mut decl = ClassDecl::new("GPUIStreamDelegate", class!(NSObject)).unwrap();
decl.add_method(
sel!(outputVideoEffectDidStartForStream:),
output_video_effect_did_start_for_stream as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(outputVideoEffectDidStopForStream:),
output_video_effect_did_stop_for_stream as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(stream:didStopWithError:),
stream_did_stop_with_error as extern "C" fn(&Object, Sel, id, id),
);
DELEGATE_CLASS = decl.register();
unsafe {
decl.add_method(
sel!(outputVideoEffectDidStartForStream:),
output_video_effect_did_start_for_stream as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(outputVideoEffectDidStopForStream:),
output_video_effect_did_stop_for_stream as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(stream:didStopWithError:),
stream_did_stop_with_error as extern "C" fn(&Object, Sel, id, id),
);
DELEGATE_CLASS = decl.register();
let mut decl = ClassDecl::new("GPUIStreamOutput", class!(NSObject)).unwrap();
decl.add_method(
sel!(stream:didOutputSampleBuffer:ofType:),
stream_did_output_sample_buffer_of_type as extern "C" fn(&Object, Sel, id, id, NSInteger),
);
decl.add_ivar::<*mut c_void>(FRAME_CALLBACK_IVAR);
let mut decl = ClassDecl::new("GPUIStreamOutput", class!(NSObject)).unwrap();
decl.add_method(
sel!(stream:didOutputSampleBuffer:ofType:),
stream_did_output_sample_buffer_of_type
as extern "C" fn(&Object, Sel, id, id, NSInteger),
);
decl.add_ivar::<*mut c_void>(FRAME_CALLBACK_IVAR);
OUTPUT_CLASS = decl.register();
OUTPUT_CLASS = decl.register();
}
}
extern "C" fn output_video_effect_did_start_for_stream(_this: &Object, _: Sel, _stream: id) {}

View file

@ -664,9 +664,11 @@ mod lenient_font_attributes {
}
unsafe fn wrap_under_get_rule(reference: CFStringRef) -> CFString {
assert!(!reference.is_null(), "Attempted to create a NULL object.");
let reference = CFRetain(reference as *const ::std::os::raw::c_void) as CFStringRef;
TCFType::wrap_under_create_rule(reference)
unsafe {
assert!(!reference.is_null(), "Attempted to create a NULL object.");
let reference = CFRetain(reference as *const ::std::os::raw::c_void) as CFStringRef;
TCFType::wrap_under_create_rule(reference)
}
}
}

View file

@ -80,7 +80,7 @@ const NSDragOperationNone: NSDragOperation = 0;
const NSDragOperationCopy: NSDragOperation = 1;
#[link(name = "CoreGraphics", kind = "framework")]
extern "C" {
unsafe extern "C" {
// Widely used private APIs; Apple uses them for their Terminal.app.
fn CGSMainConnectionID() -> id;
fn CGSSetWindowBackgroundBlurRadius(
@ -92,152 +92,155 @@ extern "C" {
#[ctor]
unsafe fn build_classes() {
WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));
PANEL_CLASS = build_window_class("GPUIPanel", class!(NSPanel));
VIEW_CLASS = {
let mut decl = ClassDecl::new("GPUIView", class!(NSView)).unwrap();
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
unsafe {
WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));
PANEL_CLASS = build_window_class("GPUIPanel", class!(NSPanel));
VIEW_CLASS = {
let mut decl = ClassDecl::new("GPUIView", class!(NSView)).unwrap();
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
unsafe {
decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel));
decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(performKeyEquivalent:),
handle_key_equivalent as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(keyDown:),
handle_key_down as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(keyUp:),
handle_key_up as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseMoved:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseExited:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseDragged:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(scrollWheel:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(swipeWithEvent:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(flagsChanged:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(performKeyEquivalent:),
handle_key_equivalent as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(keyDown:),
handle_key_down as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(keyUp:),
handle_key_up as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(rightMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseDown:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(otherMouseUp:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseMoved:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseExited:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(mouseDragged:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(scrollWheel:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(swipeWithEvent:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(flagsChanged:),
handle_view_event as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(makeBackingLayer),
make_backing_layer as extern "C" fn(&Object, Sel) -> id,
);
decl.add_method(
sel!(makeBackingLayer),
make_backing_layer as extern "C" fn(&Object, Sel) -> id,
);
decl.add_protocol(Protocol::get("CALayerDelegate").unwrap());
decl.add_method(
sel!(viewDidChangeBackingProperties),
view_did_change_backing_properties as extern "C" fn(&Object, Sel),
);
decl.add_method(
sel!(setFrameSize:),
set_frame_size as extern "C" fn(&Object, Sel, NSSize),
);
decl.add_method(
sel!(displayLayer:),
display_layer as extern "C" fn(&Object, Sel, id),
);
decl.add_protocol(Protocol::get("CALayerDelegate").unwrap());
decl.add_method(
sel!(viewDidChangeBackingProperties),
view_did_change_backing_properties as extern "C" fn(&Object, Sel),
);
decl.add_method(
sel!(setFrameSize:),
set_frame_size as extern "C" fn(&Object, Sel, NSSize),
);
decl.add_method(
sel!(displayLayer:),
display_layer as extern "C" fn(&Object, Sel, id),
);
decl.add_protocol(Protocol::get("NSTextInputClient").unwrap());
decl.add_method(
sel!(validAttributesForMarkedText),
valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id,
);
decl.add_method(
sel!(hasMarkedText),
has_marked_text as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(markedRange),
marked_range as extern "C" fn(&Object, Sel) -> NSRange,
);
decl.add_method(
sel!(selectedRange),
selected_range as extern "C" fn(&Object, Sel) -> NSRange,
);
decl.add_method(
sel!(firstRectForCharacterRange:actualRange:),
first_rect_for_character_range
as extern "C" fn(&Object, Sel, NSRange, id) -> NSRect,
);
decl.add_method(
sel!(insertText:replacementRange:),
insert_text as extern "C" fn(&Object, Sel, id, NSRange),
);
decl.add_method(
sel!(setMarkedText:selectedRange:replacementRange:),
set_marked_text as extern "C" fn(&Object, Sel, id, NSRange, NSRange),
);
decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(attributedSubstringForProposedRange:actualRange:),
attributed_substring_for_proposed_range
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,
);
decl.add_method(
sel!(viewDidChangeEffectiveAppearance),
view_did_change_effective_appearance as extern "C" fn(&Object, Sel),
);
decl.add_protocol(Protocol::get("NSTextInputClient").unwrap());
decl.add_method(
sel!(validAttributesForMarkedText),
valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id,
);
decl.add_method(
sel!(hasMarkedText),
has_marked_text as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(markedRange),
marked_range as extern "C" fn(&Object, Sel) -> NSRange,
);
decl.add_method(
sel!(selectedRange),
selected_range as extern "C" fn(&Object, Sel) -> NSRange,
);
decl.add_method(
sel!(firstRectForCharacterRange:actualRange:),
first_rect_for_character_range as extern "C" fn(&Object, Sel, NSRange, id) -> NSRect,
);
decl.add_method(
sel!(insertText:replacementRange:),
insert_text as extern "C" fn(&Object, Sel, id, NSRange),
);
decl.add_method(
sel!(setMarkedText:selectedRange:replacementRange:),
set_marked_text as extern "C" fn(&Object, Sel, id, NSRange, NSRange),
);
decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(attributedSubstringForProposedRange:actualRange:),
attributed_substring_for_proposed_range
as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,
);
decl.add_method(
sel!(viewDidChangeEffectiveAppearance),
view_did_change_effective_appearance as extern "C" fn(&Object, Sel),
);
// Suppress beep on keystrokes with modifier keys.
decl.add_method(
sel!(doCommandBySelector:),
do_command_by_selector as extern "C" fn(&Object, Sel, Sel),
);
// Suppress beep on keystrokes with modifier keys.
decl.add_method(
sel!(doCommandBySelector:),
do_command_by_selector as extern "C" fn(&Object, Sel, Sel),
);
decl.add_method(
sel!(acceptsFirstMouse:),
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(acceptsFirstMouse:),
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(characterIndexForPoint:),
character_index_for_point as extern "C" fn(&Object, Sel, NSPoint) -> u64,
);
decl.register()
};
decl.add_method(
sel!(characterIndexForPoint:),
character_index_for_point as extern "C" fn(&Object, Sel, NSPoint) -> u64,
);
}
decl.register()
};
}
}
pub(crate) fn convert_mouse_position(position: NSPoint, window_height: Pixels) -> Point<Pixels> {
@ -249,78 +252,81 @@ pub(crate) fn convert_mouse_position(position: NSPoint, window_height: Pixels) -
}
unsafe fn build_window_class(name: &'static str, superclass: &Class) -> *const Class {
let mut decl = ClassDecl::new(name, superclass).unwrap();
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
decl.add_method(sel!(dealloc), dealloc_window as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(canBecomeMainWindow),
yes as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(canBecomeKeyWindow),
yes as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(windowDidResize:),
window_did_resize as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidChangeOcclusionState:),
window_did_change_occlusion_state as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowWillEnterFullScreen:),
window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowWillExitFullScreen:),
window_will_exit_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidMove:),
window_did_move as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidChangeScreen:),
window_did_change_screen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidBecomeKey:),
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidResignKey:),
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowShouldClose:),
window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL,
);
unsafe {
let mut decl = ClassDecl::new(name, superclass).unwrap();
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
decl.add_method(sel!(dealloc), dealloc_window as extern "C" fn(&Object, Sel));
decl.add_method(sel!(close), close_window as extern "C" fn(&Object, Sel));
decl.add_method(
sel!(canBecomeMainWindow),
yes as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(canBecomeKeyWindow),
yes as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(windowDidResize:),
window_did_resize as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidChangeOcclusionState:),
window_did_change_occlusion_state as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowWillEnterFullScreen:),
window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowWillExitFullScreen:),
window_will_exit_fullscreen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidMove:),
window_did_move as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidChangeScreen:),
window_did_change_screen as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidBecomeKey:),
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowDidResignKey:),
window_did_change_key_status as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(windowShouldClose:),
window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(draggingEntered:),
dragging_entered as extern "C" fn(&Object, Sel, id) -> NSDragOperation,
);
decl.add_method(
sel!(draggingUpdated:),
dragging_updated as extern "C" fn(&Object, Sel, id) -> NSDragOperation,
);
decl.add_method(
sel!(draggingExited:),
dragging_exited as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(performDragOperation:),
perform_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(concludeDragOperation:),
conclude_drag_operation as extern "C" fn(&Object, Sel, id),
);
decl.add_method(sel!(close), close_window as extern "C" fn(&Object, Sel));
decl.register()
decl.add_method(
sel!(draggingEntered:),
dragging_entered as extern "C" fn(&Object, Sel, id) -> NSDragOperation,
);
decl.add_method(
sel!(draggingUpdated:),
dragging_updated as extern "C" fn(&Object, Sel, id) -> NSDragOperation,
);
decl.add_method(
sel!(draggingExited:),
dragging_exited as extern "C" fn(&Object, Sel, id),
);
decl.add_method(
sel!(performDragOperation:),
perform_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,
);
decl.add_method(
sel!(concludeDragOperation:),
conclude_drag_operation as extern "C" fn(&Object, Sel, id),
);
decl.register()
}
}
struct MacWindowState {
@ -913,7 +919,7 @@ impl PlatformWindow for MacWindow {
.iter()
.enumerate()
.rev()
.find(|(_, &label)| label != "Cancel")
.find(|(_, label)| **label != "Cancel")
.filter(|&(label_index, _)| label_index > 0);
unsafe {
@ -1200,16 +1206,20 @@ fn get_scale_factor(native_window: id) -> f32 {
}
unsafe fn get_window_state(object: &Object) -> Arc<Mutex<MacWindowState>> {
let raw: *mut c_void = *object.get_ivar(WINDOW_STATE_IVAR);
let rc1 = Arc::from_raw(raw as *mut Mutex<MacWindowState>);
let rc2 = rc1.clone();
mem::forget(rc1);
rc2
unsafe {
let raw: *mut c_void = *object.get_ivar(WINDOW_STATE_IVAR);
let rc1 = Arc::from_raw(raw as *mut Mutex<MacWindowState>);
let rc2 = rc1.clone();
mem::forget(rc1);
rc2
}
}
unsafe fn drop_window_state(object: &Object) {
let raw: *mut c_void = *object.get_ivar(WINDOW_STATE_IVAR);
Arc::from_raw(raw as *mut Mutex<MacWindowState>);
unsafe {
let raw: *mut c_void = *object.get_ivar(WINDOW_STATE_IVAR);
Arc::from_raw(raw as *mut Mutex<MacWindowState>);
}
}
extern "C" fn yes(_: &Object, _: Sel) -> BOOL {
@ -2069,9 +2079,11 @@ where
}
unsafe fn display_id_for_screen(screen: id) -> CGDirectDisplayID {
let device_description = NSScreen::deviceDescription(screen);
let screen_number_key: id = NSString::alloc(nil).init_str("NSScreenNumber");
let screen_number = device_description.objectForKey_(screen_number_key);
let screen_number: NSUInteger = msg_send![screen_number, unsignedIntegerValue];
screen_number as CGDirectDisplayID
unsafe {
let device_description = NSScreen::deviceDescription(screen);
let screen_number_key: id = NSString::alloc(nil).init_str("NSScreenNumber");
let screen_number = device_description.objectForKey_(screen_number_key);
let screen_number: NSUInteger = msg_send![screen_number, unsignedIntegerValue];
screen_number as CGDirectDisplayID
}
}

View file

@ -10,26 +10,28 @@ use std::ffi::CStr;
impl WindowAppearance {
pub(crate) unsafe fn from_native(appearance: id) -> Self {
let name: id = msg_send![appearance, name];
if name == NSAppearanceNameVibrantLight {
Self::VibrantLight
} else if name == NSAppearanceNameVibrantDark {
Self::VibrantDark
} else if name == NSAppearanceNameAqua {
Self::Light
} else if name == NSAppearanceNameDarkAqua {
Self::Dark
} else {
println!(
"unknown appearance: {:?}",
CStr::from_ptr(name.UTF8String())
);
Self::Light
unsafe {
if name == NSAppearanceNameVibrantLight {
Self::VibrantLight
} else if name == NSAppearanceNameVibrantDark {
Self::VibrantDark
} else if name == NSAppearanceNameAqua {
Self::Light
} else if name == NSAppearanceNameDarkAqua {
Self::Dark
} else {
println!(
"unknown appearance: {:?}",
CStr::from_ptr(name.UTF8String())
);
Self::Light
}
}
}
}
#[link(name = "AppKit", kind = "framework")]
extern "C" {
unsafe extern "C" {
pub static NSAppearanceNameAqua: id;
pub static NSAppearanceNameDarkAqua: id;
}

View file

@ -89,7 +89,7 @@ impl TestDispatcher {
self.state.lock().time = new_now;
}
pub fn simulate_random_delay(&self) -> impl 'static + Send + Future<Output = ()> {
pub fn simulate_random_delay(&self) -> impl 'static + Send + Future<Output = ()> + use<> {
struct YieldNow {
pub(crate) count: usize,
}

View file

@ -333,7 +333,7 @@ impl DirectWriteState {
&self,
font_features: &FontFeatures,
) -> Result<IDWriteTypography> {
let direct_write_features = self.components.factory.CreateTypography()?;
let direct_write_features = unsafe { self.components.factory.CreateTypography()? };
apply_font_features(&direct_write_features, font_features)?;
Ok(direct_write_features)
}
@ -352,28 +352,32 @@ impl DirectWriteState {
} else {
&self.custom_font_collection
};
let fontset = collection.GetFontSet().log_err()?;
let font = fontset
.GetMatchingFonts(
&HSTRING::from(family_name),
font_weight.into(),
DWRITE_FONT_STRETCH_NORMAL,
font_style.into(),
)
.log_err()?;
let total_number = font.GetFontCount();
let fontset = unsafe { collection.GetFontSet().log_err()? };
let font = unsafe {
fontset
.GetMatchingFonts(
&HSTRING::from(family_name),
font_weight.into(),
DWRITE_FONT_STRETCH_NORMAL,
font_style.into(),
)
.log_err()?
};
let total_number = unsafe { font.GetFontCount() };
for index in 0..total_number {
let Some(font_face_ref) = font.GetFontFaceReference(index).log_err() else {
let Some(font_face_ref) = (unsafe { font.GetFontFaceReference(index).log_err() })
else {
continue;
};
let Some(font_face) = font_face_ref.CreateFontFace().log_err() else {
let Some(font_face) = (unsafe { font_face_ref.CreateFontFace().log_err() }) else {
continue;
};
let Some(identifier) = get_font_identifier(&font_face, &self.components.locale) else {
continue;
};
let is_emoji = font_face.IsColorFont().as_bool();
let Some(direct_write_features) = self.generate_font_features(font_features).log_err()
let is_emoji = unsafe { font_face.IsColorFont().as_bool() };
let Some(direct_write_features) =
(unsafe { self.generate_font_features(font_features).log_err() })
else {
continue;
};
@ -396,14 +400,14 @@ impl DirectWriteState {
}
unsafe fn update_system_font_collection(&mut self) {
let mut collection = std::mem::zeroed();
if self
.components
.factory
.GetSystemFontCollection(false, &mut collection, true)
.log_err()
.is_some()
{
let mut collection = unsafe { std::mem::zeroed() };
if unsafe {
self.components
.factory
.GetSystemFontCollection(false, &mut collection, true)
.log_err()
.is_some()
} {
self.system_font_collection = collection.unwrap();
}
}
@ -461,35 +465,37 @@ impl DirectWriteState {
fallbacks: Option<&FontFallbacks>,
) -> Option<FontId> {
// try to find target font in custom font collection first
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
false,
)
.or_else(|| {
unsafe {
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
true,
false,
)
})
.or_else(|| {
self.update_system_font_collection();
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
true,
)
})
.or_else(|| {
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
true,
)
})
.or_else(|| {
self.update_system_font_collection();
self.get_font_id_from_font_collection(
family_name,
weight,
style,
features,
fallbacks,
true,
)
})
}
}
fn layout_line(

View file

@ -27,8 +27,8 @@ impl JsonSchema for SharedString {
String::schema_name()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
String::json_schema(gen)
fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
String::json_schema(r#gen)
}
}

View file

@ -45,7 +45,7 @@ where
&self,
emitter_key: EmitterKey,
callback: Callback,
) -> (Subscription, impl FnOnce()) {
) -> (Subscription, impl FnOnce() + use<EmitterKey, Callback>) {
let active = Rc::new(Cell::new(false));
let mut lock = self.0.lock();
let subscriber_id = post_inc(&mut lock.next_subscriber_id);
@ -88,7 +88,10 @@ where
(subscription, move || active.set(true))
}
pub fn remove(&self, emitter: &EmitterKey) -> impl IntoIterator<Item = Callback> {
pub fn remove(
&self,
emitter: &EmitterKey,
) -> impl IntoIterator<Item = Callback> + use<EmitterKey, Callback> {
let subscribers = self.0.lock().subscribers.remove(emitter);
subscribers
.unwrap_or_default()

View file

@ -133,7 +133,7 @@ impl schemars::JsonSchema for FontFeatures {
"FontFeatures".into()
}
fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
let mut schema = SchemaObject::default();
schema.instance_type = Some(schemars::schema::SingleOrVec::Single(Box::new(
InstanceType::Object,

View file

@ -936,7 +936,7 @@ impl Window {
pub(crate) fn new_focus_listener(
&self,
value: AnyWindowFocusListener,
) -> (Subscription, impl FnOnce()) {
) -> (Subscription, impl FnOnce() + use<>) {
self.focus_listeners.insert((), value)
}
}
@ -3719,11 +3719,11 @@ impl Window {
}
/// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.
pub fn handler_for<V: Render>(
pub fn handler_for<V: Render, Callback: Fn(&mut V, &mut Window, &mut Context<V>) + 'static>(
&self,
view: &Entity<V>,
f: impl Fn(&mut V, &mut Window, &mut Context<V>) + 'static,
) -> impl Fn(&mut Window, &mut App) {
f: Callback,
) -> impl Fn(&mut Window, &mut App) + use<V, Callback> {
let view = view.downgrade();
move |window: &mut Window, cx: &mut App| {
view.update(cx, |view, cx| f(view, window, cx)).ok();

View file

@ -17,7 +17,7 @@ pub fn derive_app_context(input: TokenStream) -> TokenStream {
let type_name = &ast.ident;
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
let gen = quote! {
let r#gen = quote! {
impl #impl_generics gpui::AppContext for #type_name #type_generics
#where_clause
{
@ -98,5 +98,5 @@ pub fn derive_app_context(input: TokenStream) -> TokenStream {
}
};
gen.into()
r#gen.into()
}

View file

@ -7,7 +7,7 @@ pub fn derive_into_element(input: TokenStream) -> TokenStream {
let type_name = &ast.ident;
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
let gen = quote! {
let r#gen = quote! {
impl #impl_generics gpui::IntoElement for #type_name #type_generics
#where_clause
{
@ -19,5 +19,5 @@ pub fn derive_into_element(input: TokenStream) -> TokenStream {
}
};
gen.into()
r#gen.into()
}

View file

@ -7,7 +7,7 @@ pub fn derive_render(input: TokenStream) -> TokenStream {
let type_name = &ast.ident;
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
let gen = quote! {
let r#gen = quote! {
impl #impl_generics gpui::Render for #type_name #type_generics
#where_clause
{
@ -17,5 +17,5 @@ pub fn derive_render(input: TokenStream) -> TokenStream {
}
};
gen.into()
r#gen.into()
}

View file

@ -24,7 +24,7 @@ pub fn derive_visual_context(input: TokenStream) -> TokenStream {
let type_name = &ast.ident;
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
let gen = quote! {
let r#gen = quote! {
impl #impl_generics gpui::VisualContext for #type_name #type_generics
#where_clause
{
@ -67,5 +67,5 @@ pub fn derive_visual_context(input: TokenStream) -> TokenStream {
}
};
gen.into()
r#gen.into()
}

View file

@ -1292,27 +1292,27 @@ fn border_prefixes() -> Vec<BorderStylePrefix> {
quote! { border_widths.bottom },
quote! { border_widths.left },
],
doc_string_prefix: "Sets the border width of the element. [Docs](https://tailwindcss.com/docs/border-width)"
doc_string_prefix: "Sets the border width of the element. [Docs](https://tailwindcss.com/docs/border-width)",
},
BorderStylePrefix {
prefix: "border_t",
fields: vec![quote! { border_widths.top }],
doc_string_prefix: "Sets the border width of the top side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
doc_string_prefix: "Sets the border width of the top side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)",
},
BorderStylePrefix {
prefix: "border_b",
fields: vec![quote! { border_widths.bottom }],
doc_string_prefix: "Sets the border width of the bottom side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
doc_string_prefix: "Sets the border width of the bottom side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)",
},
BorderStylePrefix {
prefix: "border_r",
fields: vec![quote! { border_widths.right }],
doc_string_prefix: "Sets the border width of the right side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
doc_string_prefix: "Sets the border width of the right side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)",
},
BorderStylePrefix {
prefix: "border_l",
fields: vec![quote! { border_widths.left }],
doc_string_prefix: "Sets the border width of the left side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
doc_string_prefix: "Sets the border width of the left side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)",
},
BorderStylePrefix {
prefix: "border_x",
@ -1320,7 +1320,7 @@ fn border_prefixes() -> Vec<BorderStylePrefix> {
quote! { border_widths.left },
quote! { border_widths.right },
],
doc_string_prefix: "Sets the border width of the vertical sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)"
doc_string_prefix: "Sets the border width of the vertical sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)",
},
BorderStylePrefix {
prefix: "border_y",
@ -1328,7 +1328,7 @@ fn border_prefixes() -> Vec<BorderStylePrefix> {
quote! { border_widths.top },
quote! { border_widths.bottom },
],
doc_string_prefix: "Sets the border width of the horizontal sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)"
doc_string_prefix: "Sets the border width of the horizontal sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)",
},
]
}

View file

@ -441,7 +441,9 @@ mod persistence {
.collect::<Vec<&str>>()
.join(", ");
let query = format!("DELETE FROM image_viewers WHERE workspace_id = ? AND item_id NOT IN ({placeholders})");
let query = format!(
"DELETE FROM image_viewers WHERE workspace_id = ? AND item_id NOT IN ({placeholders})"
);
self.write(move |conn| {
let mut statement = Statement::prepare(conn, query)?;

View file

@ -989,7 +989,7 @@ impl Buffer {
language: Option<Arc<Language>>,
language_registry: Option<Arc<LanguageRegistry>>,
cx: &mut App,
) -> impl Future<Output = BufferSnapshot> {
) -> impl Future<Output = BufferSnapshot> + use<> {
let entity_id = cx.reserve_entity::<Self>().entity_id();
let buffer_id = entity_id.as_non_zero_u64().into();
async move {
@ -1587,7 +1587,9 @@ impl Buffer {
}
}
fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, IndentSize>>> {
fn compute_autoindents(
&self,
) -> Option<impl Future<Output = BTreeMap<u32, IndentSize>> + use<>> {
let max_rows_between_yields = 100;
let snapshot = self.snapshot();
if snapshot.syntax.is_empty() || self.autoindent_requests.is_empty() {
@ -2082,23 +2084,26 @@ impl Buffer {
}
/// Waits for the buffer to receive operations with the given timestamps.
pub fn wait_for_edits(
pub fn wait_for_edits<It: IntoIterator<Item = clock::Lamport>>(
&mut self,
edit_ids: impl IntoIterator<Item = clock::Lamport>,
) -> impl Future<Output = Result<()>> {
edit_ids: It,
) -> impl Future<Output = Result<()>> + use<It> {
self.text.wait_for_edits(edit_ids)
}
/// Waits for the buffer to receive the operations necessary for resolving the given anchors.
pub fn wait_for_anchors(
pub fn wait_for_anchors<It: IntoIterator<Item = Anchor>>(
&mut self,
anchors: impl IntoIterator<Item = Anchor>,
) -> impl 'static + Future<Output = Result<()>> {
anchors: It,
) -> impl 'static + Future<Output = Result<()>> + use<It> {
self.text.wait_for_anchors(anchors)
}
/// Waits for the buffer to receive operations up to the given version.
pub fn wait_for_version(&mut self, version: clock::Global) -> impl Future<Output = Result<()>> {
pub fn wait_for_version(
&mut self,
version: clock::Global,
) -> impl Future<Output = Result<()>> + use<> {
self.text.wait_for_version(version)
}
@ -3916,91 +3921,93 @@ impl BufferSnapshot {
.map(|grammar| grammar.runnable_config.as_ref())
.collect::<Vec<_>>();
iter::from_fn(move || loop {
let mat = syntax_matches.peek()?;
iter::from_fn(move || {
loop {
let mat = syntax_matches.peek()?;
let test_range = test_configs[mat.grammar_index].and_then(|test_configs| {
let mut run_range = None;
let full_range = mat.captures.iter().fold(
Range {
start: usize::MAX,
end: 0,
},
|mut acc, next| {
let byte_range = next.node.byte_range();
if acc.start > byte_range.start {
acc.start = byte_range.start;
}
if acc.end < byte_range.end {
acc.end = byte_range.end;
}
acc
},
);
if full_range.start > full_range.end {
// We did not find a full spanning range of this match.
return None;
let test_range = test_configs[mat.grammar_index].and_then(|test_configs| {
let mut run_range = None;
let full_range = mat.captures.iter().fold(
Range {
start: usize::MAX,
end: 0,
},
|mut acc, next| {
let byte_range = next.node.byte_range();
if acc.start > byte_range.start {
acc.start = byte_range.start;
}
if acc.end < byte_range.end {
acc.end = byte_range.end;
}
acc
},
);
if full_range.start > full_range.end {
// We did not find a full spanning range of this match.
return None;
}
let extra_captures: SmallVec<[_; 1]> =
SmallVec::from_iter(mat.captures.iter().filter_map(|capture| {
test_configs
.extra_captures
.get(capture.index as usize)
.cloned()
.and_then(|tag_name| match tag_name {
RunnableCapture::Named(name) => {
Some((capture.node.byte_range(), name))
}
RunnableCapture::Run => {
let _ = run_range.insert(capture.node.byte_range());
None
}
})
}));
let run_range = run_range?;
let tags = test_configs
.query
.property_settings(mat.pattern_index)
.iter()
.filter_map(|property| {
if *property.key == *"tag" {
property
.value
.as_ref()
.map(|value| RunnableTag(value.to_string().into()))
} else {
None
}
})
.collect();
let extra_captures = extra_captures
.into_iter()
.map(|(range, name)| {
(
name.to_string(),
self.text_for_range(range.clone()).collect::<String>(),
)
})
.collect();
// All tags should have the same range.
Some(RunnableRange {
run_range,
full_range,
runnable: Runnable {
tags,
language: mat.language,
buffer: self.remote_id(),
},
extra_captures,
buffer_id: self.remote_id(),
})
});
syntax_matches.advance();
if test_range.is_some() {
// It's fine for us to short-circuit on .peek()? returning None. We don't want to return None from this iter if we
// had a capture that did not contain a run marker, hence we'll just loop around for the next capture.
return test_range;
}
let extra_captures: SmallVec<[_; 1]> =
SmallVec::from_iter(mat.captures.iter().filter_map(|capture| {
test_configs
.extra_captures
.get(capture.index as usize)
.cloned()
.and_then(|tag_name| match tag_name {
RunnableCapture::Named(name) => {
Some((capture.node.byte_range(), name))
}
RunnableCapture::Run => {
let _ = run_range.insert(capture.node.byte_range());
None
}
})
}));
let run_range = run_range?;
let tags = test_configs
.query
.property_settings(mat.pattern_index)
.iter()
.filter_map(|property| {
if *property.key == *"tag" {
property
.value
.as_ref()
.map(|value| RunnableTag(value.to_string().into()))
} else {
None
}
})
.collect();
let extra_captures = extra_captures
.into_iter()
.map(|(range, name)| {
(
name.to_string(),
self.text_for_range(range.clone()).collect::<String>(),
)
})
.collect();
// All tags should have the same range.
Some(RunnableRange {
run_range,
full_range,
runnable: Runnable {
tags,
language: mat.language,
buffer: self.remote_id(),
},
extra_captures,
buffer_id: self.remote_id(),
})
});
syntax_matches.advance();
if test_range.is_some() {
// It's fine for us to short-circuit on .peek()? returning None. We don't want to return None from this iter if we
// had a capture that did not contain a run marker, hence we'll just loop around for the next capture.
return test_range;
}
})
}
@ -4352,7 +4359,10 @@ impl<'a> BufferChunks<'a> {
} else {
// We cannot obtain new highlights for a language-aware buffer iterator, as we don't have a buffer snapshot.
// Seeking such BufferChunks is not supported.
debug_assert!(false, "Attempted to seek on a language-aware buffer iterator without associated buffer snapshot");
debug_assert!(
false,
"Attempted to seek on a language-aware buffer iterator without associated buffer snapshot"
);
}
highlights.captures.set_byte_range(self.range.clone());

View file

@ -38,7 +38,7 @@ pub use manifest::{ManifestName, ManifestProvider, ManifestQuery};
use parking_lot::Mutex;
use regex::Regex;
use schemars::{
gen::SchemaGenerator,
r#gen::SchemaGenerator,
schema::{InstanceType, Schema, SchemaObject},
JsonSchema,
};
@ -598,7 +598,9 @@ pub trait LspAdapter: 'static + Send + Sync {
/// Should not be called unless the callee is sure that
/// `Self::is_primary_zed_json_schema_adapter` returns `true`
async fn clear_zed_json_schema_cache(&self) {
unreachable!("Not implemented for this adapter. This method should only be called on the default JSON language server adapter");
unreachable!(
"Not implemented for this adapter. This method should only be called on the default JSON language server adapter"
);
}
}
@ -931,8 +933,8 @@ impl BracketPairConfig {
}
}
fn bracket_pair_config_json_schema(gen: &mut SchemaGenerator) -> Schema {
Option::<Vec<BracketPairContent>>::json_schema(gen)
fn bracket_pair_config_json_schema(r#gen: &mut SchemaGenerator) -> Schema {
Option::<Vec<BracketPairContent>>::json_schema(r#gen)
}
#[derive(Deserialize, JsonSchema)]
@ -1532,7 +1534,9 @@ impl Language {
.scope_opt_in_language_servers
.contains(server_name)
{
util::debug_panic!("Server {server_name:?} has been opted-in by scope {name:?} but has not been marked as an opt-in server");
util::debug_panic!(
"Server {server_name:?} has been opted-in by scope {name:?} but has not been marked as an opt-in server"
);
}
}

View file

@ -597,7 +597,7 @@ impl LanguageRegistry {
pub fn language_for_name(
self: &Arc<Self>,
name: &str,
) -> impl Future<Output = Result<Arc<Language>>> {
) -> impl Future<Output = Result<Arc<Language>>> + use<> {
let name = UniCase::new(name);
let rx = self.get_or_load_language(|language_name, _| {
if UniCase::new(&language_name.0) == name {

View file

@ -1300,7 +1300,7 @@ impl settings::Settings for AllLanguageSettings {
}
fn json_schema(
generator: &mut schemars::gen::SchemaGenerator,
generator: &mut schemars::r#gen::SchemaGenerator,
params: &settings::SettingsJsonSchemaParams,
_: &App,
) -> schemars::schema::RootSchema {

View file

@ -153,14 +153,14 @@ fn test_syntax_map_layers_for_range(cx: &mut App) {
syntax_map.reparse(language.clone(), &buffer);
assert_layers_for_range(
&syntax_map,
&buffer,
Point::new(2, 14)..Point::new(2, 16),
&[
"...(function_item ...",
"...(tuple_expression (call_expression ... arguments: (arguments (reference_expression value: (array_expression...",
],
);
&syntax_map,
&buffer,
Point::new(2, 14)..Point::new(2, 16),
&[
"...(function_item ...",
"...(tuple_expression (call_expression ... arguments: (arguments (reference_expression value: (array_expression...",
],
);
// Put the vec! macro back, adding back the syntactic layer.
buffer.undo();
@ -207,15 +207,15 @@ fn test_dynamic_language_injection(cx: &mut App) {
syntax_map.reparse(markdown.clone(), &buffer);
syntax_map.reparse(markdown_inline.clone(), &buffer);
assert_layers_for_range(
&syntax_map,
&buffer,
Point::new(3, 0)..Point::new(3, 0),
&[
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
"...(function_item name: (identifier) parameters: (parameters) body: (block)...",
],
);
&syntax_map,
&buffer,
Point::new(3, 0)..Point::new(3, 0),
&[
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
"...(function_item name: (identifier) parameters: (parameters) body: (block)...",
],
);
// Replace `rs` with a path to ending in `.rb` in code block.
let macro_name_range = range_for_text(&buffer, "rs");
@ -224,15 +224,15 @@ fn test_dynamic_language_injection(cx: &mut App) {
syntax_map.reparse(markdown.clone(), &buffer);
syntax_map.reparse(markdown_inline.clone(), &buffer);
assert_layers_for_range(
&syntax_map,
&buffer,
Point::new(3, 0)..Point::new(3, 0),
&[
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
"...(call method: (identifier) arguments: (argument_list (call method: (identifier) arguments: (argument_list) block: (block)...",
],
);
&syntax_map,
&buffer,
Point::new(3, 0)..Point::new(3, 0),
&[
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
"...(call method: (identifier) arguments: (argument_list (call method: (identifier) arguments: (argument_list) block: (block)...",
],
);
// Replace Ruby with a language that hasn't been loaded yet.
let macro_name_range = range_for_text(&buffer, "foo/bar/baz.rb");
@ -241,29 +241,29 @@ fn test_dynamic_language_injection(cx: &mut App) {
syntax_map.reparse(markdown.clone(), &buffer);
syntax_map.reparse(markdown_inline.clone(), &buffer);
assert_layers_for_range(
&syntax_map,
&buffer,
Point::new(3, 0)..Point::new(3, 0),
&[
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
],
);
&syntax_map,
&buffer,
Point::new(3, 0)..Point::new(3, 0),
&[
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
],
);
assert!(syntax_map.contains_unknown_injections());
registry.add(Arc::new(html_lang()));
syntax_map.reparse(markdown.clone(), &buffer);
syntax_map.reparse(markdown_inline.clone(), &buffer);
assert_layers_for_range(
&syntax_map,
&buffer,
Point::new(3, 0)..Point::new(3, 0),
&[
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
"(document (text))",
],
);
&syntax_map,
&buffer,
Point::new(3, 0)..Point::new(3, 0),
&[
"(document (section (paragraph (inline)) (fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (block_continuation) (code_fence_content (block_continuation)) (fenced_code_block_delimiter))))",
"(inline (code_span (code_span_delimiter) (code_span_delimiter)))",
"(document (text))",
],
);
assert!(!syntax_map.contains_unknown_injections());
}

View file

@ -52,7 +52,7 @@ impl RateLimiter {
pub fn stream<'a, Fut, T>(
&self,
future: Fut,
) -> impl 'a + Future<Output = Result<impl Stream<Item = T::Item>>>
) -> impl 'a + Future<Output = Result<impl Stream<Item = T::Item> + use<Fut, T>>>
where
Fut: 'a + Future<Output = Result<T>>,
T: Stream,

View file

@ -125,11 +125,21 @@ impl LanguageModelProvider for CopilotChatLanguageModelProvider {
let err = match copilot.read(cx).status() {
Status::Authorized => return Task::ready(Ok(())),
Status::Disabled => anyhow!("Copilot must be enabled for Copilot Chat to work. Please enable Copilot and try again."),
Status::Error(err) => anyhow!(format!("Received the following error while signing into Copilot: {err}")),
Status::Starting { task: _ } => anyhow!("Copilot is still starting, please wait for Copilot to start then try again"),
Status::Unauthorized => anyhow!("Unable to authorize with Copilot. Please make sure that you have an active Copilot and Copilot Chat subscription."),
Status::SignedOut {..} => anyhow!("You have signed out of Copilot. Please sign in to Copilot and try again."),
Status::Disabled => anyhow!(
"Copilot must be enabled for Copilot Chat to work. Please enable Copilot and try again."
),
Status::Error(err) => anyhow!(format!(
"Received the following error while signing into Copilot: {err}"
)),
Status::Starting { task: _ } => anyhow!(
"Copilot is still starting, please wait for Copilot to start then try again"
),
Status::Unauthorized => anyhow!(
"Unable to authorize with Copilot. Please make sure that you have an active Copilot and Copilot Chat subscription."
),
Status::SignedOut { .. } => {
anyhow!("You have signed out of Copilot. Please sign in to Copilot and try again.")
}
Status::SigningIn { prompt: _ } => anyhow!("Still signing into Copilot..."),
};
@ -398,8 +408,7 @@ impl Render for ConfigurationView {
.child(svg().size_8().path(IconName::CopilotError.path()))
}
_ => {
const LABEL: &str =
"To use Zed's assistant with GitHub Copilot, you need to be logged in to GitHub. Note that your GitHub account must have an active Copilot Chat subscription.";
const LABEL: &str = "To use Zed's assistant with GitHub Copilot, you need to be logged in to GitHub. Note that your GitHub account must have an active Copilot Chat subscription.";
v_flex().gap_6().child(Label::new(LABEL)).child(
v_flex()
.gap_2()

View file

@ -2,8 +2,7 @@ use anyhow::{anyhow, Context as _, Result};
use collections::BTreeMap;
use credentials_provider::CredentialsProvider;
use editor::{Editor, EditorElement, EditorStyle};
use futures::Stream;
use futures::{future::BoxFuture, FutureExt, StreamExt};
use futures::{future::BoxFuture, FutureExt, Stream, StreamExt};
use google_ai::{FunctionDeclaration, GenerateContentResponse, Part, UsageMetadata};
use gpui::{
AnyView, App, AsyncApp, Context, Entity, FontStyle, Subscription, Task, TextStyle, WhiteSpace,

View file

@ -415,8 +415,7 @@ impl Render for ConfigurationView {
let is_authenticated = self.state.read(cx).is_authenticated();
let lmstudio_intro = "Run local LLMs like Llama, Phi, and Qwen.";
let lmstudio_reqs =
"To use LM Studio as a provider for Zed assistant, it needs to be running with at least one model downloaded.";
let lmstudio_reqs = "To use LM Studio as a provider for Zed assistant, it needs to be running with at least one model downloaded.";
let inline_code_bg = cx.theme().colors().editor_foreground.opacity(0.05);

Some files were not shown because too many files have changed in this diff Show more