json schema, dynamic notification on schema conflict: use standard editor notifications provider

This commit is contained in:
irengrig
2016-02-19 13:24:54 +01:00
parent f715579025
commit 4827ab5da5
5 changed files with 138 additions and 70 deletions

View File

@@ -20,6 +20,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotifications;
import com.intellij.util.CollectConsumer;
import com.intellij.util.IconUtil;
import com.intellij.util.ThreeState;
@@ -183,7 +184,10 @@ public class JsonSchemaMappingsConfigurable extends MasterDetailsComponent imple
final JsonSchemaService service = JsonSchemaService.Impl.get(project);
if (service != null) service.reset();
}
if (myProject != null) DaemonCodeAnalyzer.getInstance(myProject).restart();
if (myProject != null) {
DaemonCodeAnalyzer.getInstance(myProject).restart();
EditorNotifications.getInstance(myProject).updateAllNotifications();
}
}
private static void validate(@NotNull List<JsonSchemaMappingsConfigurationBase.SchemaInfo> list) throws ConfigurationException {

View File

@@ -6,10 +6,13 @@ import com.intellij.lang.annotation.Annotator;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface JsonSchemaService {
class Impl {
@@ -30,6 +33,9 @@ public interface JsonSchemaService {
@Nullable
DocumentationProvider getDocumentationProvider(@Nullable VirtualFile file);
@Nullable
List<Pair<Boolean, String>> getMatchingSchemaDescriptors(@Nullable VirtualFile file);
boolean hasSchema(@Nullable VirtualFile file);
void reset();

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.jsonSchema.impl;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotificationPanel;
import com.intellij.ui.EditorNotifications;
import com.intellij.ui.LightColors;
import com.jetbrains.jsonSchema.JsonSchemaMappingsConfigurable;
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author Irina.Chernushina on 2/19/2016.
*/
public class JsonSchemaConflictNotificationProvider extends EditorNotifications.Provider<EditorNotificationPanel> {
private static final Key<EditorNotificationPanel> KEY = Key.create("json.schema.conflict.notification.panel");
@NotNull
private final Project myProject;
@NotNull
private final JsonSchemaService myJsonSchemaService;
public JsonSchemaConflictNotificationProvider(@NotNull Project project,
@NotNull JsonSchemaService jsonSchemaService) {
myProject = project;
myJsonSchemaService = jsonSchemaService;
}
@NotNull
@Override
public Key<EditorNotificationPanel> getKey() {
return KEY;
}
@Nullable
@Override
public EditorNotificationPanel createNotificationPanel(@NotNull VirtualFile file, @NotNull FileEditor fileEditor) {
final List<Pair<Boolean, String>> descriptors = myJsonSchemaService.getMatchingSchemaDescriptors(file);
if (descriptors == null || descriptors.size() <= 1) return null;
final String message = createMessage(descriptors);
final EditorNotificationPanel panel = new EditorNotificationPanel() {
@Override
public Color getBackground() {
return LightColors.RED;
}
};
panel.setText(message);
panel.createActionLabel("Edit JSON Schema Mappings", new Runnable() {
@Override
public void run() {
ShowSettingsUtil.getInstance().editConfigurable(myProject, new JsonSchemaMappingsConfigurable(myProject));
EditorNotifications.getInstance(myProject).updateNotifications(file);
}
});
return panel;
}
private static String createMessage(@NotNull final List<Pair<Boolean, String>> descriptors) {
boolean haveSystemSchemas = false;
for (Pair<Boolean, String> pair : descriptors) {
haveSystemSchemas |= !Boolean.TRUE.equals(pair.getFirst());
}
boolean withTypes = haveSystemSchemas;
final List<String> names = new ArrayList<>();
for (Pair<Boolean, String> pair : descriptors) {
if (withTypes) {
names.add((Boolean.TRUE.equals(pair.getFirst()) ? "user" : "system") + " schema '" + pair.getSecond() + "'");
} else {
names.add(pair.getSecond());
}
}
return "<html>There are several JSON Schemas mapped to this file: " + StringUtil.join(names, "; ") + "</html>";
}
}

View File

@@ -4,30 +4,22 @@ package com.jetbrains.jsonSchema.impl;
import com.intellij.codeInsight.completion.CompletionContributor;
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.idea.RareLogger;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.lang.documentation.CompositeDocumentationProvider;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.NotNullFunction;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.jsonSchema.JsonSchemaMappingsConfigurable;
import com.jetbrains.jsonSchema.extension.JsonSchemaFileProvider;
import com.jetbrains.jsonSchema.extension.JsonSchemaImportedProviderMarker;
import com.jetbrains.jsonSchema.extension.JsonSchemaProviderFactory;
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -77,6 +69,20 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
return wrapper != null ? wrapper.getDocumentationProvider() : null;
}
@Nullable
@Override
public List<Pair<Boolean, String>> getMatchingSchemaDescriptors(@Nullable VirtualFile file) {
final List<JsonSchemaObjectCodeInsightWrapper> wrappers = getWrappers(file);
if (wrappers == null || wrappers.isEmpty()) return null;
return ContainerUtil.map(wrappers, new NotNullFunction<JsonSchemaObjectCodeInsightWrapper, Pair<Boolean, String>>() {
@NotNull
@Override
public Pair<Boolean, String> fun(JsonSchemaObjectCodeInsightWrapper wrapper) {
return Pair.create(wrapper.isUserSchema(), wrapper.getName());
}
});
}
@Nullable
private static JsonSchemaObjectCodeInsightWrapper createWrapper(@NotNull JsonSchemaFileProvider provider) {
Reader reader = provider.getSchemaReader();
@@ -104,6 +110,15 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
@Nullable
private CodeInsightProviders getWrapper(@Nullable VirtualFile file) {
final List<JsonSchemaObjectCodeInsightWrapper> wrappers = getWrappers(file);
if (wrappers == null || wrappers.isEmpty()) {
return null;
}
return (wrappers.size() == 1 ? wrappers.get(0) : new CompositeCodeInsightProviderWithWarning(wrappers));
}
@Nullable
private List<JsonSchemaObjectCodeInsightWrapper> getWrappers(@Nullable VirtualFile file) {
if (file == null) return null;
final List<JsonSchemaObjectCodeInsightWrapper> wrappers = new ArrayList<>();
JsonSchemaProviderFactory[] factories = getProviderFactories();
@@ -123,8 +138,7 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
}
}
}
return wrappers.isEmpty() ? null : (wrappers.size() == 1 ? wrappers.get(0) : new CompositeCodeInsightProviderWithWarning(wrappers));
return wrappers;
}
private static class CompositeCodeInsightProviderWithWarning implements CodeInsightProviders {
@@ -144,69 +158,12 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
}
};
myAnnotator = new Annotator() {
private String message;
{
boolean haveSystemSchemas = false;
for (JsonSchemaObjectCodeInsightWrapper wrapper : myWrappers) {
haveSystemSchemas |= !wrapper.isUserSchema();
}
boolean withTypes = haveSystemSchemas;
final List<String> names = new ArrayList<>();
for (JsonSchemaObjectCodeInsightWrapper wrapper : myWrappers) {
if (withTypes) {
names.add((wrapper.isUserSchema() ? "user" : "system") + " schema '" + wrapper.getName() + "'");
} else {
names.add(wrapper.getName());
}
}
message = "<html>There are several JSON Schemas mapped to this file: " + StringUtil.join(names, "; ") + "</html>";
}
@Override
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
if (element instanceof PsiFile) {
addFileLevelWarning(element, holder);
}
for (JsonSchemaObjectCodeInsightWrapper wrapper : myWrappers) {
wrapper.getAnnotator().annotate(element, holder);
}
}
private void addFileLevelWarning(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
final Annotation annotation = holder.createErrorAnnotation(element, message);
annotation.setFileLevelAnnotation(true);
annotation.registerFix(new IntentionAction() {
@Nls
@NotNull
@Override
public String getText() {
return "Edit JSON Schema Mappings";
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return "JSON Schema";
}
@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 {
ShowSettingsUtil.getInstance().editConfigurable(project, new JsonSchemaMappingsConfigurable(project));
DaemonCodeAnalyzer.getInstance(project).restart(file);
}
@Override
public boolean startInWriteAction() {
return false;
}
});
}
};
final List<DocumentationProvider> list = new ArrayList<>();
for (JsonSchemaObjectCodeInsightWrapper wrapper : myWrappers) {

View File

@@ -71,6 +71,7 @@
<lang.documentationProvider language="JSON"
implementationClass="com.jetbrains.jsonSchema.ide.JsonSchemaDocumentationProvider"/>
<refactoring.elementListenerProvider implementation="com.jetbrains.jsonSchema.JsonSchemaRefactoringListenerProvider"/>
<editorNotificationProvider implementation="com.jetbrains.jsonSchema.impl.JsonSchemaConflictNotificationProvider"/>
</extensions>
<extensions defaultExtensionNs="JavaScript">
<JsonSchema.ProviderFactory implementation="com.jetbrains.jsonSchema.extension.JsonSchemaImportedProviderFactory"/>