Skip to content

Commit

Permalink
Fix #436 Search .clang-format file in parent folders, before creating…
Browse files Browse the repository at this point in the history
… it (#444)

Fixes #436
  • Loading branch information
travkin79 authored Feb 26, 2025
1 parent 8a64cd0 commit ccf1be4
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 26 deletions.
3 changes: 2 additions & 1 deletion bundles/org.eclipse.cdt.lsp.clangd/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ Require-Bundle: org.eclipse.cdt.lsp;bundle-version="0.0.0",
org.eclipse.core.variables;bundle-version="0.0.0",
org.yaml.snakeyaml;bundle-version="0.0.0",
org.eclipse.tm4e.language_pack;bundle-version="0.0.0",
org.eclipse.ui.console;bundle-version="0.0.0"
org.eclipse.ui.console;bundle-version="0.0.0",
org.eclipse.core.filesystem
Service-Component: OSGI-INF/org.eclipse.cdt.lsp.clangd.internal.config.ClangFormatFileHandler.xml,
OSGI-INF/org.eclipse.cdt.lsp.clangd.internal.config.ClangdCommandLineValidator.xml,
OSGI-INF/org.eclipse.cdt.lsp.clangd.internal.config.ClangdConfigurationAccess.xml,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
public interface ClangFormatFile {

/**
* Opens the .clang-format file in the given project. Creates a file with default values, if not yet existing prior to the opening.
* Opens the .clang-format file in the given project or in one of its parent directories.
* Creates a file with default values, if not yet existing prior to the opening.
* @param formatFile
*/
void openClangFormatFile(IProject project);

/**
* Creates a new .clang-format file with default settings in the project root directory if not yet existing.
* Creates a new .clang-format file with default settings in the project root directory if not yet existing
* or uses an existing file on one of the project's parent directories.
* @param project
*/
void createClangFormatFile(IProject project);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
* to add error markers to the modified <code>.clang-format</code> file.
*/
public class ClangFormatFileMonitor {
private static final String CLANG_FORMAT_FILE = ".clang-format"; //$NON-NLS-1$
public static final String CLANG_FORMAT_FILE = ".clang-format"; //$NON-NLS-1$
public static final String CLANG_FORMAT_CHECK_FILE = "clang-format-check"; //$NON-NLS-1$
private final ConcurrentLinkedQueue<IFile> pendingFiles = new ConcurrentLinkedQueue<>();
private final IWorkspace workspace;
Expand Down Expand Up @@ -76,13 +76,13 @@ public ClangFormatFileMonitor(IWorkspace workspace) {
this.workspace = workspace;
}

private final WorkspaceJob checkJob = new WorkspaceJob("Check .clang-format file") { //$NON-NLS-1$
private final WorkspaceJob checkJob = new WorkspaceJob("Check " + CLANG_FORMAT_FILE + " file") { //$NON-NLS-1$ //$NON-NLS-2$

@Override
public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
var clangdPath = getClangdPath();
if (clangdPath.isEmpty()) {
String msg = "Cannot determine clangd path for .clang-format file validation"; //$NON-NLS-1$
String msg = "Cannot determine clangd path for " + CLANG_FORMAT_FILE + " file validation"; //$NON-NLS-1$ //$NON-NLS-2$
Platform.getLog(getClass()).error(msg);
return Status.error(msg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
package org.eclipse.cdt.lsp.clangd.internal.config;

import java.io.IOException;
import java.net.URI;

import org.eclipse.cdt.lsp.clangd.ClangFormatFile;
import org.eclipse.cdt.lsp.clangd.format.ClangFormatFileMonitor;
import org.eclipse.cdt.lsp.clangd.plugin.ClangdPlugin;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
Expand All @@ -31,15 +35,14 @@

@Component(property = { "service.ranking:Integer=0" })
public final class ClangFormatFileHandler implements ClangFormatFile {
public static final String format_file = ".clang-format"; //$NON-NLS-1$

/**
* Opens the .clang-format file in the given project. Creates a file with default values, if not yet existing prior to the opening.
* @param formatFile
*/
@Override
public void openClangFormatFile(IProject project) {
runClangFormatFileCreatorJob(project, true);
findOrCreateClangFormatFile(project, true);
}

/**
Expand All @@ -48,27 +51,62 @@ public void openClangFormatFile(IProject project) {
*/
@Override
public void createClangFormatFile(IProject project) {
runClangFormatFileCreatorJob(project, false);
findOrCreateClangFormatFile(project, false);
}

private void runClangFormatFileCreatorJob(IProject project, boolean openFile) {
var formatFile = project.getFile(format_file);
WorkbenchJob job = new WorkbenchJob("Create " + format_file + " file") { //$NON-NLS-1$ //$NON-NLS-2$
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
return createFileFromResource(formatFile);
}
private void findOrCreateClangFormatFile(IProject project, boolean openFile) {
IFile formatFileInProject = project.getFile(ClangFormatFileMonitor.CLANG_FORMAT_FILE);
IFileStore formatFileInParentFolder = null;

if (!formatFileInProject.exists()) {
formatFileInParentFolder = findClangFormatFileInParentFolders(project);
}

boolean createFormatFile = !formatFileInProject.exists() && formatFileInParentFolder == null;

@Override
public void performDone(IJobChangeEvent event) {
if (openFile) {
LSPEclipseUtils.open(formatFile.getLocationURI().toString(), null);
if (createFormatFile) {
WorkbenchJob job = new WorkbenchJob("Create " + ClangFormatFileMonitor.CLANG_FORMAT_FILE + " file") { //$NON-NLS-1$ //$NON-NLS-2$
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
return createFileFromResource(formatFileInProject);
}
}
};
job.setSystem(true);
job.setRule(formatFile.getWorkspace().getRuleFactory().createRule(formatFile));
job.schedule();

@Override
public void performDone(IJobChangeEvent event) {
if (openFile) {
openClangFormatFile(formatFileInProject.getLocationURI());
}
}
};
job.setSystem(true);
job.setRule(formatFileInProject.getWorkspace().getRuleFactory().createRule(formatFileInProject));
job.schedule();
} else if (openFile) {
URI formatFileUri = (formatFileInParentFolder != null) ? formatFileInParentFolder.toURI()
: formatFileInProject.getLocationURI();
openClangFormatFile(formatFileUri);
}
}

private void openClangFormatFile(URI fileUri) {
LSPEclipseUtils.open(fileUri.toString(), null);
}

private IFileStore findClangFormatFileInParentFolders(IProject project) {
IFileStore currentDirStore = EFS.getLocalFileSystem().getStore(project.getLocation());
IFileStore clangFormatFileStore = currentDirStore.getChild(ClangFormatFileMonitor.CLANG_FORMAT_FILE);

while (!clangFormatFileStore.fetchInfo().exists() && currentDirStore.getParent() != null
&& currentDirStore.getParent().fetchInfo().exists()) {
// move up one level to the parent directory and check again
currentDirStore = currentDirStore.getParent();
clangFormatFileStore = currentDirStore.getChild(ClangFormatFileMonitor.CLANG_FORMAT_FILE);
}

if (clangFormatFileStore.fetchInfo().exists()) {
return clangFormatFileStore;
}
return null;
}

private IStatus createFileFromResource(IFile formatFile) {
Expand All @@ -77,7 +115,8 @@ private IStatus createFileFromResource(IFile formatFile) {
formatFile.create(source, true, new NullProgressMonitor());
} catch (IOException | CoreException e) {
Platform.getLog(getClass()).error(e.getMessage(), e);
return new Status(IStatus.ERROR, ClangdPlugin.PLUGIN_ID, "Cannot create " + format_file + " file", e); //$NON-NLS-1$ //$NON-NLS-2$
return new Status(IStatus.ERROR, ClangdPlugin.PLUGIN_ID,
"Cannot create " + ClangFormatFileMonitor.CLANG_FORMAT_FILE + " file", e); //$NON-NLS-1$ //$NON-NLS-2$
}
}
return Status.OK_STATUS;
Expand Down

0 comments on commit ccf1be4

Please sign in to comment.