mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
WEB-24726 JSON Schema: highlight unresolved $ref references
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This inspection checks that '$ref' and '$schema' paths are valid<br>
|
||||
</body>
|
||||
</html>
|
||||
@@ -25,7 +25,7 @@ inspection.compliance.option.trailing.comma=Warn about trailing commas
|
||||
inspection.compliance.option.nan.infinity=Warn about NaN and Infinity/-Infinity numeric values
|
||||
|
||||
inspection.duplicate.keys.name=Duplicate keys in object literals
|
||||
inspection.duplicate.keys.msg.duplicate.keys=Object contains duplicate keys "{0}"
|
||||
inspection.duplicate.keys.msg.duplicate.keys=Object contains duplicate keys ''{0}''
|
||||
|
||||
# Formatter
|
||||
formatter.align.properties.caption=Align
|
||||
@@ -51,6 +51,12 @@ json.schema.file.not.found=File not found
|
||||
json.schema.inspection.compliance.name=Compliance with JSON schema
|
||||
json.schema.inspection.case.insensitive.enum=Case insensitive matching for enum values
|
||||
|
||||
json.schema.ref.refs.inspection.name=Unresolved '$ref' and '$schema' references
|
||||
json.schema.ref.file.not.found=File ''{0}'' not found
|
||||
json.schema.ref.cannot.resolve.path=Cannot resolve path ''{0}''
|
||||
json.schema.ref.no.array.element=Array doesn''t contain element with index '{0}'
|
||||
json.schema.ref.no.property=Property ''{0}'' not found
|
||||
|
||||
settings.json.schema.add.mapping=Add mapping
|
||||
settings.json.schema.edit.mapping=Edit mapping
|
||||
settings.json.schema.remove.mapping=Remove mapping
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.jsonSchema.impl.inspections;
|
||||
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.json.psi.JsonFile;
|
||||
import com.intellij.json.psi.JsonValue;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaObject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class JsonSchemaBasedInspectionBase extends LocalInspectionTool {
|
||||
@NotNull
|
||||
@Override
|
||||
public HighlightDisplayLevel getDefaultLevel() {
|
||||
return HighlightDisplayLevel.WARNING;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly, @NotNull LocalInspectionToolSession session) {
|
||||
PsiFile file = holder.getFile();
|
||||
JsonValue root = file instanceof JsonFile ? ObjectUtils.tryCast(file.getFirstChild(), JsonValue.class) : null;
|
||||
if (root == null) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
|
||||
JsonSchemaService service = JsonSchemaService.Impl.get(file.getProject());
|
||||
VirtualFile virtualFile = file.getViewProvider().getVirtualFile();
|
||||
if (!service.isApplicableToFile(virtualFile)) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(virtualFile);
|
||||
|
||||
return doBuildVisitor(root, rootSchema, service, holder, session);
|
||||
}
|
||||
|
||||
protected abstract PsiElementVisitor doBuildVisitor(@NotNull JsonValue root,
|
||||
@Nullable JsonSchemaObject schema,
|
||||
@NotNull JsonSchemaService service,
|
||||
@NotNull ProblemsHolder holder,
|
||||
@NotNull LocalInspectionToolSession session);
|
||||
}
|
||||
+10
-26
@@ -1,28 +1,25 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.jsonSchema.impl;
|
||||
package com.jetbrains.jsonSchema.impl.inspections;
|
||||
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
|
||||
import com.intellij.json.JsonBundle;
|
||||
import com.intellij.json.psi.JsonElementVisitor;
|
||||
import com.intellij.json.psi.JsonFile;
|
||||
import com.intellij.json.psi.JsonValue;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.jetbrains.jsonSchema.extension.JsonLikePsiWalker;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import com.jetbrains.jsonSchema.impl.JsonComplianceCheckerOptions;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaComplianceChecker;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaObject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class JsonSchemaComplianceInspection extends LocalInspectionTool {
|
||||
public class JsonSchemaComplianceInspection extends JsonSchemaBasedInspectionBase {
|
||||
public boolean myCaseInsensitiveEnum = false;
|
||||
|
||||
@Override
|
||||
@@ -31,24 +28,11 @@ public class JsonSchemaComplianceInspection extends LocalInspectionTool {
|
||||
return JsonBundle.message("json.schema.inspection.compliance.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HighlightDisplayLevel getDefaultLevel() {
|
||||
return HighlightDisplayLevel.WARNING;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly, @NotNull LocalInspectionToolSession session) {
|
||||
PsiFile file = holder.getFile();
|
||||
JsonValue root = file instanceof JsonFile ? ObjectUtils.tryCast(file.getFirstChild(), JsonValue.class) : null;
|
||||
if (root == null) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
|
||||
JsonSchemaService service = JsonSchemaService.Impl.get(file.getProject());
|
||||
VirtualFile virtualFile = file.getViewProvider().getVirtualFile();
|
||||
if (!service.isApplicableToFile(virtualFile)) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(virtualFile);
|
||||
if (rootSchema == null) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
protected PsiElementVisitor doBuildVisitor(@NotNull JsonValue root, @Nullable JsonSchemaObject schema, @NotNull JsonSchemaService service,
|
||||
@NotNull ProblemsHolder holder,
|
||||
@NotNull LocalInspectionToolSession session) {
|
||||
if (schema == null) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
JsonComplianceCheckerOptions options = new JsonComplianceCheckerOptions(myCaseInsensitiveEnum);
|
||||
|
||||
return new JsonElementVisitor() {
|
||||
@@ -56,7 +40,7 @@ public class JsonSchemaComplianceInspection extends LocalInspectionTool {
|
||||
public void visitElement(PsiElement element) {
|
||||
if (element == root) {
|
||||
// perform this only for the root element, because the checker traverses the hierarchy itself
|
||||
annotate(element, rootSchema, holder, session, options);
|
||||
annotate(element, schema, holder, session, options);
|
||||
}
|
||||
super.visitElement(element);
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.jetbrains.jsonSchema.impl.inspections;
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.json.JsonBundle;
|
||||
import com.intellij.json.psi.*;
|
||||
import com.intellij.openapi.paths.WebReference;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaObject;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class JsonSchemaRefReferenceInspection extends JsonSchemaBasedInspectionBase {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return JsonBundle.message("json.schema.ref.refs.inspection.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiElementVisitor doBuildVisitor(@NotNull JsonValue root,
|
||||
@Nullable JsonSchemaObject schema,
|
||||
@NotNull JsonSchemaService service,
|
||||
@NotNull ProblemsHolder holder,
|
||||
@NotNull LocalInspectionToolSession session) {
|
||||
boolean checkRefs = schema != null && service.isSchemaFile(schema.getSchemaFile());
|
||||
return new JsonElementVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement element) {
|
||||
if (element == root) {
|
||||
if (element instanceof JsonObject) {
|
||||
final JsonProperty schemaProp = ((JsonObject)element).findProperty("$schema");
|
||||
if (schemaProp != null) {
|
||||
doCheck(schemaProp.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
super.visitElement(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProperty(@NotNull JsonProperty o) {
|
||||
if (!checkRefs) return;
|
||||
if ("$ref".equals(o.getName())) {
|
||||
doCheck(o.getValue());
|
||||
}
|
||||
super.visitProperty(o);
|
||||
}
|
||||
|
||||
private void doCheck(JsonValue value) {
|
||||
if (!(value instanceof JsonStringLiteral)) return;
|
||||
for (PsiReference reference : value.getReferences()) {
|
||||
if (reference instanceof WebReference) continue;
|
||||
final PsiElement resolved = reference.resolve();
|
||||
if (resolved == null) {
|
||||
holder.registerProblem(reference, getReferenceErrorDesc(reference), ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getReferenceErrorDesc(PsiReference reference) {
|
||||
final String text = reference.getCanonicalText();
|
||||
if (reference instanceof FileReference) {
|
||||
final int hash = text.indexOf('#');
|
||||
return JsonBundle.message("json.schema.ref.file.not.found", hash == -1 ? text : text.substring(0, hash));
|
||||
}
|
||||
final int lastSlash = text.lastIndexOf('/');
|
||||
if (lastSlash == -1) {
|
||||
return JsonBundle.message("json.schema.ref.cannot.resolve.path", text);
|
||||
}
|
||||
final String substring = text.substring(text.lastIndexOf('/') + 1);
|
||||
|
||||
try {
|
||||
Integer.parseInt(substring);
|
||||
return JsonBundle.message("json.schema.ref.no.array.element", substring);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return JsonBundle.message("json.schema.ref.no.property", substring);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -25,9 +25,9 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.jsonSchema.extension.JsonSchemaFileProvider;
|
||||
import com.jetbrains.jsonSchema.extension.JsonSchemaProjectSelfProviderFactory;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaComplianceInspection;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaObject;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaVersion;
|
||||
import com.jetbrains.jsonSchema.impl.inspections.JsonSchemaComplianceInspection;
|
||||
import com.jetbrains.jsonSchema.schemaFile.TestJsonSchemaMappingsProjectConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Assert;
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.util.containers.Predicate;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaComplianceInspection;
|
||||
import com.jetbrains.jsonSchema.impl.inspections.JsonSchemaComplianceInspection;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.ExpectedHighlightingData;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.util.containers.Predicate;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaComplianceInspection;
|
||||
import com.jetbrains.jsonSchema.impl.inspections.JsonSchemaComplianceInspection;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ package com.jetbrains.jsonSchema;
|
||||
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.testFramework.ExpectedHighlightingData;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaComplianceInspection;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaVersion;
|
||||
import com.jetbrains.jsonSchema.impl.inspections.JsonSchemaComplianceInspection;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.intellij.json.JsonLanguage;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.Predicate;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaComplianceInspection;
|
||||
import com.jetbrains.jsonSchema.impl.inspections.JsonSchemaComplianceInspection;
|
||||
|
||||
public class JsonSchemaQuickFixTest extends JsonSchemaQuickFixTestBase {
|
||||
@Override
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.jetbrains.jsonSchema.JsonSchemaTestServiceImpl;
|
||||
import com.jetbrains.jsonSchema.extension.JsonSchemaFileProvider;
|
||||
import com.jetbrains.jsonSchema.extension.JsonSchemaProjectSelfProviderFactory;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import com.jetbrains.jsonSchema.impl.inspections.JsonSchemaComplianceInspection;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"foo": {
|
||||
<warning descr="Object contains duplicate keys \\"foo\\"">"foo"</warning>: 1,
|
||||
<warning descr="Object contains duplicate keys \\"foo\\"">'foo'</warning>: 2,
|
||||
<warning descr="Object contains duplicate keys \\"foo\\"">foo</warning>: 3,
|
||||
<warning descr="Object contains duplicate keys \\"foo\\"">"\u0066\u006f\u006f"</warning>: {
|
||||
<warning descr="Object contains duplicate keys 'foo'">"foo"</warning>: 1,
|
||||
<warning descr="Object contains duplicate keys 'foo'">'foo'</warning>: 2,
|
||||
<warning descr="Object contains duplicate keys 'foo'">foo</warning>: 3,
|
||||
<warning descr="Object contains duplicate keys 'foo'">"\u0066\u006f\u006f"</warning>: {
|
||||
"foo": 4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,11 @@
|
||||
<localInspection language="JSON" shortName="JsonSchemaCompliance"
|
||||
bundle="com.intellij.json.JsonBundle" key="json.schema.inspection.compliance.name" groupKey="json.inspection.group"
|
||||
enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.jetbrains.jsonSchema.impl.JsonSchemaComplianceInspection"/>
|
||||
implementationClass="com.jetbrains.jsonSchema.impl.inspections.JsonSchemaComplianceInspection"/>
|
||||
<localInspection language="JSON" shortName="JsonSchemaRefReference"
|
||||
bundle="com.intellij.json.JsonBundle" key="json.schema.ref.refs.inspection.name" groupKey="json.inspection.group"
|
||||
enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.jetbrains.jsonSchema.impl.inspections.JsonSchemaRefReferenceInspection" />
|
||||
|
||||
<lang.elementManipulator forClass="com.intellij.json.psi.JsonStringLiteral"
|
||||
implementationClass="com.intellij.json.psi.JsonStringLiteralManipulator"/>
|
||||
|
||||
Reference in New Issue
Block a user