(&self, params: DocumentFormattingParams)
| 1123 | } |
| 1124 | |
| 1125 | async fn formatting(&self, params: DocumentFormattingParams) -> Result<Option<Vec<TextEdit>>> { |
| 1126 | let uri = params.text_document.uri.to_string(); |
| 1127 | let config = self.config(); |
| 1128 | |
| 1129 | // Read Composer metadata for require-dev detection and bin-dir. |
| 1130 | let workspace_root = self.workspace_root.read().clone(); |
| 1131 | let composer_json: Option<composer::ComposerPackage> = workspace_root |
| 1132 | .as_deref() |
| 1133 | .and_then(composer::read_composer_package); |
| 1134 | let bin_dir: Option<String> = composer_json.as_ref().map(composer::get_bin_dir); |
| 1135 | |
| 1136 | // Resolve the formatting strategy: external tools, built-in, or disabled. |
| 1137 | let strategy = formatting::resolve_strategy( |
| 1138 | workspace_root.as_deref(), |
| 1139 | &config.formatting, |
| 1140 | composer_json.as_ref(), |
| 1141 | bin_dir.as_deref(), |
| 1142 | ); |
| 1143 | |
| 1144 | // Resolve the file path from the URI for config discovery. |
| 1145 | let file_path = Url::parse(&uri).ok().and_then(|u| u.to_file_path().ok()); |
| 1146 | let file_path = match file_path { |
| 1147 | Some(p) => p, |
| 1148 | None => return Ok(None), |
| 1149 | }; |
| 1150 | |
| 1151 | // Get the file content. |
| 1152 | let content = match self.get_file_content(&uri) { |
| 1153 | Some(c) => c, |
| 1154 | None => return Ok(None), |
| 1155 | }; |
| 1156 | |
| 1157 | let php_version = self.php_version(); |
| 1158 | |
| 1159 | // Execute the resolved formatting strategy on a blocking thread |
| 1160 | // to avoid stalling the async runtime while external tools run. |
| 1161 | let formatting_config = config.formatting.clone(); |
| 1162 | let result = tokio::task::spawn_blocking(move || { |
| 1163 | formatting::execute_strategy( |
| 1164 | &strategy, |
| 1165 | &content, |
| 1166 | &file_path, |
| 1167 | &formatting_config, |
| 1168 | php_version, |
| 1169 | ) |
| 1170 | }) |
| 1171 | .await; |
| 1172 | |
| 1173 | match result { |
| 1174 | Ok(Ok(edits)) => Ok(edits), |
| 1175 | Ok(Err(e)) => { |
| 1176 | self.log(MessageType::ERROR, format!("Formatting failed: {}", e)) |
| 1177 | .await; |
| 1178 | Err(tower_lsp::jsonrpc::Error { |
| 1179 | code: tower_lsp::jsonrpc::ErrorCode::InternalError, |
| 1180 | message: format!("Formatting failed: {}", e).into(), |
| 1181 | data: None, |
| 1182 | }) |
nothing calls this directly
no test coverage detected