Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: handle IDE-wide code-style settings #99

Merged
merged 5 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/js/codestyle/patchJavaSrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ ${Object.entries(categoryGroups).map(([category, groups]) =>
).join('\n')}
${t}}
${t}public CdsCodeStyleSettings(CodeStyleSettings settings) {
${t}${t}super("CDSCodeStyleSettings", settings);
${t}${t}super(settings);
${t}}

${options.map(opt => `${t}public ${opt.fieldType} ${opt.name} = ${opt.default};`).join('\n')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public class CdsCodeStyleSettings extends CdsCodeStyleSettingsBase {
CATEGORY_GROUPS.put(Category.OTHER, Set.of("Other"));
}
public CdsCodeStyleSettings(CodeStyleSettings settings) {
super("CDSCodeStyleSettings", settings);
super(settings);
}

public boolean alignActionNames = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.sap.cap.cds.intellij.codestyle;

import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
import com.sap.cap.cds.intellij.codestyle.CdsCodeStyleOption.Category;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;

Expand All @@ -18,8 +18,8 @@ public abstract class CdsCodeStyleSettingsBase extends CustomCodeStyleSettings {
public static final Map<String, CdsCodeStyleOption> OPTIONS = new LinkedHashMap<>();
public static final Map<Category, Set<String>> CATEGORY_GROUPS = new LinkedHashMap<>();

public CdsCodeStyleSettingsBase(@NonNls @NotNull String tagName, @NotNull CodeStyleSettings container) {
super(tagName, container);
CdsCodeStyleSettingsBase(@NotNull CodeStyleSettings container) {
super("CDSCodeStyleSettings", container);
}

private static String getEnumLabel(String name, int id) {
Expand All @@ -30,7 +30,8 @@ private static int getEnumId(CdsCodeStyleOption option, String label) {
return Arrays.stream(option.values).filter(v -> v.getLabel().equals(label)).findFirst().orElseThrow().getId();
}

public void loadFrom(JSONObject json) {
public void loadFrom(String prettierJson) {
var json = new JSONObject(prettierJson);
OPTIONS.forEach((name, option) -> {
if (!json.has(name)) {
return;
Expand All @@ -50,6 +51,24 @@ public void loadFrom(JSONObject json) {
});
}

public boolean equals(String prettierJson) {
CodeStyleSettings container = CodeStyleSettingsManager.getInstance().createSettings();
CdsCodeStyleSettings other = container.getCustomSettings(CdsCodeStyleSettings.class);
other.loadFrom(prettierJson);
return this.equals(other);
}

public boolean equals(CdsCodeStyleSettings other) {
return OPTIONS.keySet().stream()
.allMatch(name -> {
try {
return Objects.equals(getFieldValue(this, name, null), getFieldValue(other, name, null));
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}

public JSONObject getNonDefaultSettings() {
var map = OPTIONS.entrySet().stream()
.map(optionEntry -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
import com.intellij.openapi.components.Service;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsChangeEvent;
import com.intellij.psi.codeStyle.CodeStyleSettingsListener;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileWriter;
Expand Down Expand Up @@ -39,6 +39,10 @@ public void codeStyleSettingsChanged(@NotNull CodeStyleSettingsChangeEvent event
});
}

private static @NotNull CdsCodeStyleSettings getIdeSettings() {
return CodeStyle.getDefaultSettings().getCustomSettings(CdsCodeStyleSettings.class);
}

public boolean isSettingsFilePresent() {
return prettierJsonManager.isJsonFilePresent();
}
Expand All @@ -59,6 +63,13 @@ public void updateProjectSettingsFromFile() {
prettierJsonManager.reset();
CodeStyle.setMainProjectSettings(project, CodeStyleSettingsManager.getInstance(project).createSettings());
}
} else if (isSettingsFilePresent()) { // deletion of .cdsprettier.json has no effect
String prettierJson = prettierJsonManager.readJson();
if (prettierJson != null && !getIdeSettings().equals(prettierJson)) {
CodeStyleSettings projectSettings = CodeStyleSettingsManager.getInstance().createSettings();
projectSettings.getCustomSettings(CdsCodeStyleSettings.class).loadFrom(prettierJson);
CodeStyle.setMainProjectSettings(project, projectSettings);
}
}
}

Expand All @@ -71,7 +82,7 @@ private final class CdsPrettierJsonManager {
static final int JSON_INDENT = 2;

File jsonFile;
String jsonWritten;
String jsonCached;

CdsPrettierJsonManager() {
// assuming no changes to project directory
Expand All @@ -93,7 +104,7 @@ void loadSettingsFromFile(@NotNull CdsCodeStyleSettings settings) {
String json = readJson();
if (json != null) {
try {
settings.loadFrom(new JSONObject(json));
settings.loadFrom(json);
} catch (JSONException e) {
logger.error("Failed to parse JSON '%s'".formatted(json), e);
}
Expand All @@ -105,7 +116,7 @@ private String readJson() {
return null;
}
try {
return readString(jsonFile.toPath());
return jsonCached = readString(jsonFile.toPath());
} catch (IOException e) {
logger.error("Failed to read [%s]".formatted(jsonFile), e);
}
Expand All @@ -117,7 +128,7 @@ void saveSettingsToFile(@NotNull CdsCodeStyleSettings settings) {
return;
}
String json = settings.getNonDefaultSettings().toString(JSON_INDENT);
if (json.equals(jsonWritten)) {
if (json.equals(jsonCached)) {
return;
}
if (!jsonFile.getParentFile().exists()) {
Expand All @@ -126,14 +137,14 @@ void saveSettingsToFile(@NotNull CdsCodeStyleSettings settings) {
}
try (FileWriter writer = new FileWriter(jsonFile)) {
writer.write(json);
jsonWritten = json;
jsonCached = json;
} catch (IOException e) {
logger.error("Failed to write [%s]".formatted(jsonFile), e);
}
}

void reset() {
jsonWritten = null;
jsonCached = null;
}

@NotNull File getJsonFile(String projectDir) {
Expand All @@ -145,7 +156,7 @@ void reset() {
}

public boolean isSettingsReallyChanged() {
return jsonWritten == null || !jsonWritten.equals(readJson());
return jsonCached == null || !jsonCached.equals(readJson());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.sap.cap.cds.intellij.codestyle;

import com.intellij.application.options.CodeStyle;

import java.io.IOException;

public class CdsCodeStyleSettingsServiceIdeSettingsTest extends CdsCodeStyleSettingsServiceTestBase {

@Override
protected void setUp() throws Exception {
super.setUp();
setPerProjectSettings(false); // → CodeStyle.getSettings(project) will return "Default" (IDE) code-style settings via CodeStyleSchemes.getInstance().findPreferredScheme()
}

public void testDefaultSettings() {
openProject();
assertEquals(defaults.tabSize, getCdsCodeStyleSettings().tabSize);
}

public void testUsesIdeSettings() {
openProject();
assertFalse(CodeStyle.usesOwnSettings(project));
}

// Direction .cdsprettier.json → settings

public void testPrettierJsonLifecycle() throws IOException, InterruptedException {
openProject();
createPrettierJson();
writePrettierJson("{}");
assertEquals(defaults.tabSize, getCdsCodeStyleSettings().tabSize);
assertFalse(CodeStyle.usesOwnSettings(project));

writePrettierJson("{ tabSize: 42 }");
assertEquals(42, getCdsCodeStyleSettings().tabSize);
assertTrue(CodeStyle.usesOwnSettings(project));

deletePrettierJson();
assertEquals(defaults.tabSize, getCdsCodeStyleSettings().tabSize);
assertTrue(CodeStyle.usesOwnSettings(project));
}

public void testPrettierJsonDeletedFirst() throws IOException, InterruptedException {
createPrettierJson();
writePrettierJson("{}");
openProject();
assertFalse(CodeStyle.usesOwnSettings(project));

deletePrettierJson();
assertEquals(defaults.tabSize, getCdsCodeStyleSettings().tabSize);
assertFalse(CodeStyle.usesOwnSettings(project));
}

public void testExistentPrettierJsonWithSameSettings() throws IOException, InterruptedException {
createPrettierJson();
writePrettierJson("{}");
openProject();
assertFalse(CodeStyle.usesOwnSettings(project));
}

public void testExistentPrettierJsonWithDifferingSettings() throws IOException, InterruptedException {
createPrettierJson();
writePrettierJson("{ tabSize: 42 }");
openProject();
assertEquals(42, getCdsCodeStyleSettings().tabSize);
assertTrue(CodeStyle.usesOwnSettings(project));
}

// TODO Direction settings → .cdsprettier.json

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.sap.cap.cds.intellij.codestyle;

import com.intellij.application.options.CodeStyle;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

Expand All @@ -14,16 +17,21 @@ protected void setUp() throws Exception {
setPerProjectSettings(true);
}

// TODO test other direction
public void testUsesProjectSettings() {
openProject();
assertTrue(CodeStyle.usesOwnSettings(project));
}

public void testDefaultSettings() {
openProject();
assertEquals(defaults.tabSize, getCdsCodeStyleSettings().tabSize);
}

// Direction .cdsprettier.json → settings

public void testPrettierJsonLifecycle() throws IOException, InterruptedException {
loadProject();
assertEquals(defaults.tabSize, getCdsCodeStyleSettings().tabSize);

openProject();
createPrettierJson();

writePrettierJson("{}");
assertEquals(defaults.tabSize, getCdsCodeStyleSettings().tabSize);

Expand All @@ -37,7 +45,7 @@ public void testPrettierJsonLifecycle() throws IOException, InterruptedException
public void testExistentPrettierJson() throws Exception {
createPrettierJson();
writePrettierJson("{ tabSize: 42 }");
loadProject();
openProject();
assertEquals(42, getCdsCodeStyleSettings().tabSize);
}

Expand All @@ -49,10 +57,25 @@ public void testInvalidPrettierJson() {
} catch (IOException e) {
throw new RuntimeException(e);
}
loadProject();
openProject();
});
assertInstanceOf(exception, JSONException.class);
assertEquals(defaults.tabSize, getCdsCodeStyleSettings().tabSize);
}

// Direction settings → .cdsprettier.json

public void testCdsPrettierJsonCreation() throws IOException {
openProject();
assertEquals("{}", readPrettierJson()); // from project settings
}

public void testSettingChanged() throws IOException {
openProject();
getCdsCodeStyleSettings().tabSize = 42;
CodeStyleSettingsManager.getInstance(project).notifyCodeStyleSettingsChanged();

assertEquals(42, new JSONObject(readPrettierJson()).get("tabSize"));
}

}
Loading
Loading