Resolve prettier config on server init

Kirill Bulatov created

Change summary

crates/prettier/src/prettier.rs        |  1 +
crates/prettier/src/prettier_server.js | 20 +++++++++++++++-----
crates/project/src/project.rs          | 24 +++++++++++++++++++++++-
3 files changed, 39 insertions(+), 6 deletions(-)

Detailed changes

crates/prettier/src/prettier.rs 🔗

@@ -222,6 +222,7 @@ impl Prettier {
                 text: buffer.text(),
                 options: FormatOptions {
                     parser,
+                    // TODO kb is not absolute now
                     path,
                     tab_width,
                 },

crates/prettier/src/prettier_server.js 🔗

@@ -21,18 +21,27 @@ fs.stat(prettierContainerPath, (err, stats) => {
 });
 const prettierPath = path.join(prettierContainerPath, 'node_modules/prettier');
 
+class Prettier {
+    constructor(path, prettier, config) {
+        this.path = path;
+        this.prettier = prettier;
+        this.config = config;
+    }
+}
 
 (async () => {
     let prettier;
+    let config;
     try {
         prettier = await loadPrettier(prettierPath);
+        config = await prettier.resolveConfig(prettierPath) || {};
     } catch (e) {
         process.stderr.write(`Failed to load prettier: ${e}\n`);
         process.exit(1);
     }
-    process.stderr.write("Prettier loadded successfully\n");
+    process.stderr.write(`Prettier at path '${prettierPath}' loaded successfully, config: ${config}\n`);
     process.stdin.resume();
-    handleBuffer(prettier);
+    handleBuffer(new Prettier(prettierPath, prettier, config));
 })()
 
 async function handleBuffer(prettier) {
@@ -121,7 +130,7 @@ async function* readStdin() {
     }
 }
 
-// ?
+// TODO kb, more methods?
 // shutdown
 // error
 async function handleMessage(message, prettier) {
@@ -140,10 +149,11 @@ async function handleMessage(message, prettier) {
         if (params.options === undefined) {
             throw new Error(`Message params.options is undefined: ${JSON.stringify(message)}`);
         }
-        const formattedText = await prettier.format(params.text, params.options);
+        const formattedText = await prettier.prettier.format(params.text, { ...prettier.config, ...params.options });
         sendResponse({ id, result: { text: formattedText } });
     } else if (method === 'prettier/clear_cache') {
-        prettier.clearConfigCache();
+        prettier.prettier.clearConfigCache();
+        prettier.config = await prettier.prettier.resolveConfig(prettier.path) || {};
         sendResponse({ id, result: null });
     } else if (method === 'initialize') {
         sendResponse({

crates/project/src/project.rs 🔗

@@ -911,7 +911,7 @@ impl Project {
                 .detach();
         }
 
-        // TODO kb restart all formatters if settings change
+        // TODO kb restart all default formatters if Zed prettier settings change
         for (worktree, language, settings) in language_formatters_to_check {
             self.maybe_start_default_formatters(worktree, &language, &settings, cx);
         }
@@ -5987,6 +5987,7 @@ impl Project {
                     this.update_local_worktree_buffers(&worktree, changes, cx);
                     this.update_local_worktree_language_servers(&worktree, changes, cx);
                     this.update_local_worktree_settings(&worktree, changes, cx);
+                    this.update_prettier_settings(&worktree, changes, cx);
                     cx.emit(Event::WorktreeUpdatedEntries(
                         worktree.read(cx).id(),
                         changes.clone(),
@@ -6366,6 +6367,27 @@ impl Project {
         .detach();
     }
 
+    fn update_prettier_settings(
+        &self,
+        worktree: &ModelHandle<Worktree>,
+        changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
+        cx: &mut ModelContext<'_, Project>,
+    ) {
+        let prettier_config_files = Prettier::CONFIG_FILE_NAMES
+            .iter()
+            .map(Path::new)
+            .collect::<HashSet<_>>();
+        let prettier_config_changes = changes
+            .iter()
+            .filter(|(path, _, _)| prettier_config_files.contains(path.as_ref()))
+            .collect::<Vec<_>>();
+        dbg!(prettier_config_changes);
+        dbg!(changes.len());
+        // TODO kb: reset caches for all worktree-related prettiers (including the default one) on prettier config file _changes_
+        // prepare node + prettier + plugins + prettier_server on files with Languages that have prettier formatter. Do not start it yet.
+        // !! Ignore **/node_modules/** files in both checks above.
+    }
+
     pub fn set_active_path(&mut self, entry: Option<ProjectPath>, cx: &mut ModelContext<Self>) {
         let new_active_entry = entry.and_then(|project_path| {
             let worktree = self.worktree_for_id(project_path.worktree_id, cx)?;