mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
WEB-20367 JSON Schema: provide validation warning for the file under several schemas
Use all schemas available for the file; display warning message with quick fix to edit settings
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.jetbrains.jsonSchema;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.json.JsonBundle;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
@@ -185,6 +186,7 @@ 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();
|
||||
}
|
||||
|
||||
private static void validate(@NotNull List<JsonSchemaMappingsConfigurationBase.SchemaInfo> list) throws ConfigurationException {
|
||||
|
||||
@@ -12,4 +12,7 @@ public interface JsonSchemaFileProvider {
|
||||
|
||||
@Nullable
|
||||
Reader getSchemaReader();
|
||||
|
||||
@NotNull
|
||||
String getName();
|
||||
}
|
||||
|
||||
@@ -43,16 +43,21 @@ public class JsonSchemaImportedProviderFactory implements JsonSchemaProviderFact
|
||||
final Map<String, JsonSchemaMappingsConfigurationBase.SchemaInfo> map = configuration.getStateMap();
|
||||
for (JsonSchemaMappingsConfigurationBase.SchemaInfo info : map.values()) {
|
||||
if (!info.getPatterns().isEmpty()) {
|
||||
list.add(new MyProvider(project, configuration.convertToAbsoluteFile(info.getRelativePathToSchema()), info.getPatterns()));
|
||||
list.add(new MyProvider(project, info.getName(), configuration.convertToAbsoluteFile(info.getRelativePathToSchema()), info.getPatterns()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyProvider implements JsonSchemaFileProvider, JsonSchemaImportedProviderMarker {
|
||||
@NotNull private final String myName;
|
||||
@NotNull private final File myFile;
|
||||
@NotNull private final List<Processor<VirtualFile>> myPatterns;
|
||||
|
||||
public MyProvider(@Nullable final Project project, @NotNull File file, @NotNull List<JsonSchemaMappingsConfigurationBase.Item> patterns) {
|
||||
public MyProvider(@Nullable final Project project,
|
||||
@NotNull String name,
|
||||
@NotNull File file,
|
||||
@NotNull List<JsonSchemaMappingsConfigurationBase.Item> patterns) {
|
||||
myName = name;
|
||||
myFile = file;
|
||||
myPatterns = new ArrayList<Processor<VirtualFile>>();
|
||||
for (final JsonSchemaMappingsConfigurationBase.Item pattern : patterns) {
|
||||
@@ -95,6 +100,12 @@ public class JsonSchemaImportedProviderFactory implements JsonSchemaProviderFact
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull VirtualFile file) {
|
||||
if (file.isDirectory() || !file.isValid()) return false;
|
||||
|
||||
@@ -52,6 +52,12 @@ public class JsonSchemaSelfProviderFactory implements JsonSchemaProviderFactory
|
||||
return content == null ? null : new StringReader(content);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "schema.json";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getContent() {
|
||||
ClassLoader loader = JsonSchemaSelfProviderFactory.class.getClassLoader();
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.lang.documentation.DocumentationProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 2/18/2016.
|
||||
*/
|
||||
public interface CodeInsightProviders {
|
||||
@NotNull
|
||||
CompletionContributor getContributor();
|
||||
|
||||
@NotNull
|
||||
Annotator getAnnotator();
|
||||
|
||||
@NotNull
|
||||
DocumentationProvider getDocumentationProvider();
|
||||
}
|
||||
@@ -6,7 +6,9 @@ import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.lang.documentation.DocumentationProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
class JsonSchemaObjectCodeInsightWrapper {
|
||||
class JsonSchemaObjectCodeInsightWrapper implements CodeInsightProviders {
|
||||
@NotNull private final String myName;
|
||||
private boolean myIsUserSchema;
|
||||
|
||||
@NotNull
|
||||
private final CompletionContributor myContributor;
|
||||
@@ -16,24 +18,42 @@ class JsonSchemaObjectCodeInsightWrapper {
|
||||
@NotNull
|
||||
private final DocumentationProvider myDocumentationProvider;
|
||||
|
||||
public JsonSchemaObjectCodeInsightWrapper(@NotNull JsonSchemaObject schemaObject) {
|
||||
public JsonSchemaObjectCodeInsightWrapper(@NotNull String name, @NotNull JsonSchemaObject schemaObject) {
|
||||
myName = name;
|
||||
myContributor = new JsonBySchemaObjectCompletionContributor(schemaObject);
|
||||
myAnnotator = new JsonBySchemaObjectAnnotator(schemaObject);
|
||||
myDocumentationProvider = new JsonBySchemaDocumentationProvider(schemaObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public CompletionContributor getContributor() {
|
||||
return myContributor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Annotator getAnnotator() {
|
||||
return myAnnotator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public DocumentationProvider getDocumentationProvider() {
|
||||
return myDocumentationProvider;
|
||||
}
|
||||
|
||||
public JsonSchemaObjectCodeInsightWrapper setUserSchema(boolean userSchema) {
|
||||
myIsUserSchema = userSchema;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isUserSchema() {
|
||||
return myIsUserSchema;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,38 @@ 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.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
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;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
@@ -38,25 +55,25 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
|
||||
@Nullable
|
||||
public Annotator getAnnotator(@Nullable VirtualFile file) {
|
||||
JsonSchemaObjectCodeInsightWrapper wrapper = getWrapper(file);
|
||||
CodeInsightProviders wrapper = getWrapper(file);
|
||||
return wrapper != null ? wrapper.getAnnotator() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CompletionContributor getCompletionContributor(@Nullable VirtualFile file) {
|
||||
JsonSchemaObjectCodeInsightWrapper wrapper = getWrapper(file);
|
||||
CodeInsightProviders wrapper = getWrapper(file);
|
||||
return wrapper != null ? wrapper.getContributor() : null;
|
||||
}
|
||||
|
||||
public boolean hasSchema(@Nullable VirtualFile file) {
|
||||
JsonSchemaObjectCodeInsightWrapper wrapper = getWrapper(file);
|
||||
CodeInsightProviders wrapper = getWrapper(file);
|
||||
return wrapper != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DocumentationProvider getDocumentationProvider(@Nullable VirtualFile file) {
|
||||
JsonSchemaObjectCodeInsightWrapper wrapper = getWrapper(file);
|
||||
CodeInsightProviders wrapper = getWrapper(file);
|
||||
return wrapper != null ? wrapper.getDocumentationProvider() : null;
|
||||
}
|
||||
|
||||
@@ -66,7 +83,7 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
try {
|
||||
if (reader != null) {
|
||||
JsonSchemaObject resultObject = new JsonSchemaReader().read(reader);
|
||||
return new JsonSchemaObjectCodeInsightWrapper(resultObject);
|
||||
return new JsonSchemaObjectCodeInsightWrapper(provider.getName(), resultObject).setUserSchema(provider instanceof JsonSchemaImportedProviderMarker);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -86,8 +103,9 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JsonSchemaObjectCodeInsightWrapper getWrapper(@Nullable VirtualFile file) {
|
||||
private CodeInsightProviders getWrapper(@Nullable VirtualFile file) {
|
||||
if (file == null) return null;
|
||||
final List<JsonSchemaObjectCodeInsightWrapper> wrappers = new ArrayList<>();
|
||||
JsonSchemaProviderFactory[] factories = getProviderFactories();
|
||||
for (JsonSchemaProviderFactory factory : factories) {
|
||||
for (JsonSchemaFileProvider provider : factory.getProviders(myProject)) {
|
||||
@@ -99,13 +117,120 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
myWrappers.putIfAbsent(provider, newWrapper);
|
||||
wrapper = myWrappers.get(provider);
|
||||
}
|
||||
|
||||
if (wrapper != null) {
|
||||
return wrapper;
|
||||
wrappers.add(wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
return wrappers.isEmpty() ? null : (wrappers.size() == 1 ? wrappers.get(0) : new CompositeCodeInsightProviderWithWarning(wrappers));
|
||||
}
|
||||
|
||||
private static class CompositeCodeInsightProviderWithWarning implements CodeInsightProviders {
|
||||
private final List<JsonSchemaObjectCodeInsightWrapper> myWrappers;
|
||||
private CompletionContributor myContributor;
|
||||
private Annotator myAnnotator;
|
||||
private DocumentationProvider myDocumentationProvider;
|
||||
|
||||
public CompositeCodeInsightProviderWithWarning(List<JsonSchemaObjectCodeInsightWrapper> wrappers) {
|
||||
myWrappers = wrappers;
|
||||
myContributor = new CompletionContributor() {
|
||||
@Override
|
||||
public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) {
|
||||
for (JsonSchemaObjectCodeInsightWrapper wrapper : myWrappers) {
|
||||
wrapper.getContributor().fillCompletionVariants(parameters, result);
|
||||
}
|
||||
}
|
||||
};
|
||||
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) {
|
||||
list.add(wrapper.getDocumentationProvider());
|
||||
}
|
||||
myDocumentationProvider = CompositeDocumentationProvider.wrapProviders(list);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CompletionContributor getContributor() {
|
||||
return myContributor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Annotator getAnnotator() {
|
||||
return myAnnotator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DocumentationProvider getDocumentationProvider() {
|
||||
return myDocumentationProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,4 +28,10 @@ public class JsonSchemaTestProvider implements JsonSchemaFileProvider {
|
||||
public Reader getSchemaReader() {
|
||||
return new StringReader(mySchemaText);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user