diff --git a/plugins/editorconfig/src/icons/EditorconfigIcons.java b/plugins/editorconfig/src/icons/EditorconfigIcons.java new file mode 100644 index 000000000000..ff1eb313974c --- /dev/null +++ b/plugins/editorconfig/src/icons/EditorconfigIcons.java @@ -0,0 +1,17 @@ +package icons; + +import com.intellij.openapi.util.IconLoader; + +import javax.swing.*; + +/** + * NOTE THIS FILE IS AUTO-GENERATED + * DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead + */ +public class EditorconfigIcons { + private static Icon load(String path) { + return IconLoader.getIcon(path, EditorconfigIcons.class); + } + + public static final Icon Editorconfig = load("/org/editorconfig/icons/editorconfig.png"); // 16x16 +} diff --git a/plugins/editorconfig/src/org/editorconfig/Utils.java b/plugins/editorconfig/src/org/editorconfig/Utils.java index 6781229ce405..1f08a0752f91 100644 --- a/plugins/editorconfig/src/org/editorconfig/Utils.java +++ b/plugins/editorconfig/src/org/editorconfig/Utils.java @@ -27,10 +27,6 @@ public class Utils { EditorConfigNotifier.getInstance().error(project, configValue, "\"" + configValue + "\" is not a valid value" + (!configKey.isEmpty() ? " for " + configKey : "") + " for file " + filePath); } - public static void appliedConfigMessage(Project project, String configValue, String configKey, String filePath) { - EditorConfigNotifier.getInstance().info(project, "Applied .editorconfig settings"); - } - public static String getFilePath(Project project, VirtualFile file) { if (!file.isInLocalFileSystem()) { return project.getBasePath() + "/" + file.getNameWithoutExtension() + "." + file.getFileType().getDefaultExtension(); diff --git a/plugins/editorconfig/src/org/editorconfig/annotations/EditorConfigAnnotator.java b/plugins/editorconfig/src/org/editorconfig/annotations/EditorConfigAnnotator.java new file mode 100644 index 000000000000..c4c9eab1a4b1 --- /dev/null +++ b/plugins/editorconfig/src/org/editorconfig/annotations/EditorConfigAnnotator.java @@ -0,0 +1,126 @@ +package org.editorconfig.annotations; + +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.lang.annotation.Annotation; +import com.intellij.lang.annotation.AnnotationHolder; +import com.intellij.lang.annotation.Annotator; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.markup.GutterIconRenderer; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ObjectUtils; +import icons.EditorconfigIcons; +import org.editorconfig.Utils; +import org.editorconfig.core.EditorConfig; +import org.editorconfig.plugincomponents.SettingsProviderComponent; +import org.editorconfig.settings.EditorConfigSettings; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.List; + +/** + * @author Dennis.Ushakov + */ +public class EditorConfigAnnotator implements Annotator { + private static final String EDITOR_CONFIG_ACCEPTED = "editor.config.accepted"; + + @Override + public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { + PsiFile file = ObjectUtils.tryCast(element, PsiFile.class); + if (file == null) { + return; + } + final Project project = file.getProject(); + final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings(); + if (!Utils.isEnabled(settings) || PropertiesComponent.getInstance(project).getBoolean(EDITOR_CONFIG_ACCEPTED, false)) return; + final List pairs = SettingsProviderComponent.getInstance().getOutPairs(project, Utils.getFilePath(project, file.getVirtualFile())); + if (!pairs.isEmpty()) { + final Annotation annotation = holder.createInfoAnnotation(file, "EditorConfig is overriding Code Style settings for this file"); + annotation.setFileLevelAnnotation(true); + annotation.setGutterIconRenderer(new MyGutterIconRenderer()); + annotation.registerFix(new IntentionAction() { + @NotNull + @Override + public String getText() { + return "Disable EditorConfig support"; + } + + @NotNull + @Override + public String getFamilyName() { + return "EditorConfig"; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return true; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + settings.getCustomSettings(EditorConfigSettings.class).ENABLED = false; + DaemonCodeAnalyzer.getInstance(project).restart(); + } + + @Override + public boolean startInWriteAction() { + return false; + } + }); + annotation.registerFix(new IntentionAction() { + @NotNull + @Override + public String getText() { + return "Dismiss"; + } + + @NotNull + @Override + public String getFamilyName() { + return "EditorConfig"; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return false; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + PropertiesComponent.getInstance(project).setValue(EDITOR_CONFIG_ACCEPTED, "true"); + DaemonCodeAnalyzer.getInstance(project).restart(); + } + + @Override + public boolean startInWriteAction() { + return false; + } + }); + } + } + + private static class MyGutterIconRenderer extends GutterIconRenderer { + @NotNull + @Override + public Icon getIcon() { + return EditorconfigIcons.Editorconfig; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof MyGutterIconRenderer; + } + + @Override + public int hashCode() { + return EditorconfigIcons.Editorconfig.hashCode(); + } + } +} diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorConfigIndentOptionsProvider.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorConfigIndentOptionsProvider.java index 273b11e223d2..756377d2e4aa 100644 --- a/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorConfigIndentOptionsProvider.java +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorConfigIndentOptionsProvider.java @@ -66,7 +66,6 @@ public class EditorConfigIndentOptionsProvider extends FileIndentOptionsProvider final String calculatedTabWidth = calculateTabWidth(tabWidth, indentSize); if (!calculatedIndentSize.isEmpty()) { if (applyIndentSize(indentOptions, calculatedIndentSize)) { - Utils.appliedConfigMessage(project, calculatedIndentSize, indentSizeKey, filePath); changed = true; } else { Utils.invalidConfigMessage(project, calculatedIndentSize, indentSizeKey, filePath); @@ -74,7 +73,6 @@ public class EditorConfigIndentOptionsProvider extends FileIndentOptionsProvider } if (!calculatedContinuationSize.isEmpty()) { if (applyContinuationIndentSize(indentOptions, calculatedContinuationSize)) { - Utils.appliedConfigMessage(project, calculatedContinuationSize, continuationSizeKey, filePath); changed = true; } else { @@ -83,7 +81,6 @@ public class EditorConfigIndentOptionsProvider extends FileIndentOptionsProvider } if (!calculatedTabWidth.isEmpty()) { if (applyTabWidth(indentOptions, calculatedTabWidth)) { - Utils.appliedConfigMessage(project, calculatedTabWidth, tabWidthKey, filePath); changed = true; } else { @@ -92,7 +89,6 @@ public class EditorConfigIndentOptionsProvider extends FileIndentOptionsProvider } if (!indentStyle.isEmpty()) { if (applyIndentStyle(indentOptions, indentStyle)) { - Utils.appliedConfigMessage(project, indentStyle, indentStyleKey, filePath); changed = true; } else { diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java index 25cf2d046585..0e4c06929f68 100644 --- a/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java @@ -84,7 +84,6 @@ public class EditorSettingsManager extends FileDocumentManagerAdapter { } else { file.putUserData(userDataKey, data); - Utils.appliedConfigMessage(myProject, configValue, editorConfigKey, file.getCanonicalPath()); } } } diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java index 8a744f5ff0df..278b684e10d2 100644 --- a/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java @@ -67,7 +67,6 @@ public class EncodingManager extends FileDocumentManagerAdapter { if (newCharset != null) { if (Comparing.equal(newCharset, file.getCharset())) return; encodingProjectManager.setEncoding(file, newCharset); - Utils.appliedConfigMessage(myProject, charset, charsetKey, filePath); } else { Utils.invalidConfigMessage(myProject, charset, charsetKey, filePath); } diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java index 03896aa5aaa4..a65d00796699 100644 --- a/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java +++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java @@ -84,7 +84,6 @@ public class LineEndingsManager extends FileDocumentManagerAdapter { statusBarUpdated = true; updateStatusBar(); } - Utils.appliedConfigMessage(myProject, lineEndings, lineEndingsKey, filePath); } } catch (IllegalArgumentException e) { diff --git a/plugins/editorconfig/src/org/editorconfig/icons/editorconfig.png b/plugins/editorconfig/src/org/editorconfig/icons/editorconfig.png new file mode 100644 index 000000000000..636d757dbc42 Binary files /dev/null and b/plugins/editorconfig/src/org/editorconfig/icons/editorconfig.png differ diff --git a/plugins/editorconfig/src/org/editorconfig/icons/editorconfig@2x.png b/plugins/editorconfig/src/org/editorconfig/icons/editorconfig@2x.png new file mode 100644 index 000000000000..d65e6a7fb035 Binary files /dev/null and b/plugins/editorconfig/src/org/editorconfig/icons/editorconfig@2x.png differ diff --git a/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java index d35a216d0b9d..feeebb8de1c0 100644 --- a/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java +++ b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java @@ -1,7 +1,11 @@ package org.editorconfig.plugincomponents; +import com.intellij.lang.LanguageAnnotators; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; @@ -13,6 +17,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import org.editorconfig.Utils; +import org.editorconfig.annotations.EditorConfigAnnotator; import org.editorconfig.core.EditorConfig; import org.editorconfig.core.EditorConfig.OutPair; import org.editorconfig.core.EditorConfigException; @@ -24,8 +29,18 @@ import java.util.*; public class SettingsProviderComponent implements ApplicationComponent { private EditorConfig editorConfig; - public SettingsProviderComponent() { + public SettingsProviderComponent(FileTypeManager manager) { editorConfig = new EditorConfig(); + registerAnnotator(manager); + } + + public void registerAnnotator(FileTypeManager manager) { + final EditorConfigAnnotator annotator = new EditorConfigAnnotator(); + for (FileType type : manager.getRegisteredFileTypes()) { + if (type instanceof LanguageFileType) { + LanguageAnnotators.INSTANCE.addExplicitExtension(((LanguageFileType)type).getLanguage(), annotator); + } + } } public static SettingsProviderComponent getInstance() {