mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
WEB-20415 JSON Schema: support references to definitions
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.json.JsonLanguage;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 4/1/2016.
|
||||
*/
|
||||
public class JsonSchemaFileType extends LanguageFileType implements FileTypeIdentifiableByVirtualFile {
|
||||
public static JsonSchemaFileType INSTANCE = new JsonSchemaFileType();
|
||||
|
||||
public JsonSchemaFileType() {
|
||||
super(JsonLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "JSON Schema";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "JSON Schema file";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDefaultExtension() {
|
||||
return "json";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Icon getIcon() {//todo change icon
|
||||
return AllIcons.FileTypes.Json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMyFileType(@NotNull VirtualFile file) {
|
||||
final Project project = ProjectUtil.guessProjectForFile(file);
|
||||
return project != null && JsonSchemaMappingsProjectConfiguration.getInstance(project).isRegisteredSchemaFile(file);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileTypeConsumer;
|
||||
import com.intellij.openapi.fileTypes.FileTypeFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 4/1/2016.
|
||||
*/
|
||||
public class JsonSchemaFileTypeFactory extends FileTypeFactory {
|
||||
@Override
|
||||
public void createFileTypes(@NotNull FileTypeConsumer consumer) {
|
||||
consumer.consume(JsonSchemaFileType.INSTANCE);
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -15,13 +15,13 @@
|
||||
*/
|
||||
package com.jetbrains.jsonSchema.extension;
|
||||
|
||||
import com.intellij.json.JsonFileType;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ResourceUtil;
|
||||
import com.jetbrains.jsonSchema.JsonSchemaFileType;
|
||||
import com.jetbrains.jsonSchema.JsonSchemaMappingsProjectConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -38,6 +38,7 @@ import java.util.List;
|
||||
*/
|
||||
public class JsonSchemaProjectSelfProviderFactory {
|
||||
private static final Logger LOG = Logger.getInstance("#com.jetbrains.jsonSchema.extension.JsonSchemaProjectSelfProviderFactory");
|
||||
public static final String SCHEMA_JSON_FILE_NAME = "schema.json";
|
||||
private final List<JsonSchemaFileProvider<Object>> myProviders;
|
||||
|
||||
public static JsonSchemaProjectSelfProviderFactory getInstance(final Project project) {
|
||||
@@ -62,7 +63,7 @@ public class JsonSchemaProjectSelfProviderFactory {
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull VirtualFile file) {
|
||||
if (myProject == null || !JsonFileType.INSTANCE.equals(file.getFileType())) return false;
|
||||
if (myProject == null || !JsonSchemaFileType.INSTANCE.equals(file.getFileType())) return false;
|
||||
return JsonSchemaMappingsProjectConfiguration.getInstance(myProject).isRegisteredSchemaFile(file);
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ public class JsonSchemaProjectSelfProviderFactory {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "schema.json";
|
||||
return SCHEMA_JSON_FILE_NAME;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.extension.schema;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiReferenceBase;
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 3/31/2016.
|
||||
*/
|
||||
public abstract class JsonSchemaBaseReference<T extends PsiElement> extends PsiReferenceBase<T> {
|
||||
public JsonSchemaBaseReference(T element, TextRange textRange) {
|
||||
super(element, textRange, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement resolve() {
|
||||
return ResolveCache.getInstance(getElement().getProject()).resolveWithCaching(this, MyResolver.INSTANCE, false, false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract PsiElement resolveInner();
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
JsonSchemaBaseReference that = (JsonSchemaBaseReference)o;
|
||||
|
||||
if (!myElement.equals(that.myElement)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myElement.hashCode();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] getVariants() {
|
||||
return ArrayUtil.EMPTY_OBJECT_ARRAY;
|
||||
}
|
||||
|
||||
private static class MyResolver implements ResolveCache.Resolver {
|
||||
private static final MyResolver INSTANCE = new MyResolver();
|
||||
|
||||
@Nullable
|
||||
public PsiElement resolve(@NotNull PsiReference ref, boolean incompleteCode) {
|
||||
return ((JsonSchemaBaseReference)ref).resolveInner();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.extension.schema;
|
||||
|
||||
import com.intellij.json.psi.JsonFile;
|
||||
import com.intellij.json.psi.JsonProperty;
|
||||
import com.intellij.json.psi.impl.JsonRecursiveElementVisitor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.indexing.*;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.IntInlineKeyDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import com.jetbrains.jsonSchema.JsonSchemaFileType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 4/1/2016.
|
||||
*/
|
||||
public class JsonSchemaFileIndex extends FileBasedIndexExtension<String, Integer> {
|
||||
public static final ID<String, Integer> PROPERTIES_INDEX = ID.create("json.schema.properties.index");
|
||||
public static final int VERSION = 1;
|
||||
private IntInlineKeyDescriptor myKeyDescriptor = new IntInlineKeyDescriptor();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ID<String, Integer> getName() {
|
||||
return PROPERTIES_INDEX;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DataIndexer<String, Integer, FileContent> getIndexer() {
|
||||
return new DataIndexer<String, Integer, FileContent>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Integer> map(@NotNull FileContent inputData) {
|
||||
final Map<String, Integer> map = new HashMap<>();
|
||||
final PsiFile file = inputData.getPsiFile();
|
||||
if (file instanceof JsonFile) {
|
||||
file.accept(new JsonRecursiveElementVisitor() {
|
||||
private String myPrefix = "";
|
||||
@Override
|
||||
public void visitProperty(@NotNull JsonProperty property) {
|
||||
String wasPrefix = myPrefix;
|
||||
myPrefix = myPrefix + "/" + property.getName();
|
||||
map.put(myPrefix, property.getTextRange().getStartOffset());
|
||||
super.visitProperty(property);
|
||||
myPrefix = wasPrefix;
|
||||
}
|
||||
});
|
||||
}
|
||||
return map;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public KeyDescriptor<String> getKeyDescriptor() {
|
||||
return EnumeratorStringDescriptor.INSTANCE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DataExternalizer<Integer> getValueExternalizer() {
|
||||
return myKeyDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FileBasedIndex.InputFilter getInputFilter() {
|
||||
return new DefaultFileTypeSpecificInputFilter(JsonSchemaFileType.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dependsOnFileContent() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.extension.schema;
|
||||
|
||||
import com.intellij.json.psi.JsonValue;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 3/31/2016.
|
||||
*/
|
||||
public class JsonSchemaRefReferenceProvider extends PsiReferenceProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||
return new PsiReference[] {new JsonSchemaRefReference((JsonValue)element)};
|
||||
}
|
||||
|
||||
private static class JsonSchemaRefReference extends JsonSchemaBaseReference<JsonValue> {
|
||||
public JsonSchemaRefReference(JsonValue element) {
|
||||
super(element, ElementManipulators.getValueTextRange(element));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCanonicalText() {
|
||||
return StringUtil.unquoteString(super.getCanonicalText());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement resolveInner() {
|
||||
final FileBasedIndex index = FileBasedIndex.getInstance();
|
||||
final String text = getCanonicalText();
|
||||
String id = null;
|
||||
String ref = text.substring(1);
|
||||
if (!text.startsWith("#")) {
|
||||
final int idx = text.indexOf("#");
|
||||
if (idx <= 0) return null;
|
||||
id = text.substring(0, idx);
|
||||
ref = text.substring(idx + 1);
|
||||
}
|
||||
|
||||
final Ref<Pair<VirtualFile, Integer>> reference = new Ref<>();
|
||||
final GlobalSearchScope filter = id == null ? GlobalSearchScope.fileScope(getElement().getContainingFile()) :
|
||||
GlobalSearchScope.allScope(getElement().getProject());
|
||||
String finalId = id;
|
||||
index.processValues(JsonSchemaFileIndex.PROPERTIES_INDEX, ref, null, new FileBasedIndex.ValueProcessor<Integer>() {
|
||||
@Override
|
||||
public boolean process(VirtualFile file, Integer value) {
|
||||
if (finalId != null) {
|
||||
if (!JsonSchemaService.Impl.getEx(getElement().getProject()).checkFileForId(finalId, file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
reference.set(Pair.create(file, value));
|
||||
return false;
|
||||
}
|
||||
}, filter);
|
||||
|
||||
if (!reference.isNull()) {
|
||||
final Pair<VirtualFile, Integer> pair = reference.get();
|
||||
final PsiFile file = getElement().getManager().findFile(pair.getFirst());
|
||||
if (file != null) {
|
||||
return file.findElementAt(pair.getSecond());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.extension.schema;
|
||||
|
||||
import com.intellij.json.psi.JsonProperty;
|
||||
import com.intellij.json.psi.JsonValue;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReferenceContributor;
|
||||
import com.intellij.psi.PsiReferenceRegistrar;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.filters.position.FilterPattern;
|
||||
import com.jetbrains.jsonSchema.JsonSchemaFileType;
|
||||
import com.jetbrains.jsonSchema.JsonSchemaMappingsProjectConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 3/31/2016.
|
||||
*/
|
||||
public class JsonSchemaReferenceContributor extends PsiReferenceContributor {
|
||||
private static final PsiElementPattern.Capture<JsonValue> REF_PATTERN = createPropertyValuePattern("$ref");
|
||||
|
||||
@Override
|
||||
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
|
||||
registrar.registerReferenceProvider(REF_PATTERN, new JsonSchemaRefReferenceProvider());
|
||||
}
|
||||
|
||||
private static PsiElementPattern.Capture<JsonValue> createPropertyValuePattern(@NotNull final String propertyName) {
|
||||
return PlatformPatterns.psiElement(JsonValue.class).and(new FilterPattern(new ElementFilter() {
|
||||
@Override
|
||||
public boolean isAcceptable(Object element, @Nullable PsiElement context) {
|
||||
if (element instanceof JsonValue) {
|
||||
if (!isSchemaFile((PsiElement)element)) return false;
|
||||
if (((JsonValue)element).getParent() instanceof JsonProperty &&
|
||||
((JsonProperty)((JsonValue)element).getParent()).getValue() == element) {
|
||||
return propertyName.equals(((JsonProperty)((JsonValue)element).getParent()).getName());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClassAcceptable(Class hintClass) {
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private static boolean isSchemaFile(@NotNull final PsiElement element) {
|
||||
final Project project = element.getProject();
|
||||
final PsiFile file = element.getContainingFile();
|
||||
if (!JsonSchemaFileType.INSTANCE.equals(file.getFileType())) return false;
|
||||
return file.getVirtualFile() != null &&
|
||||
JsonSchemaMappingsProjectConfiguration.getInstance(project).isRegisteredSchemaFile(file.getVirtualFile());
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaServiceEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -18,12 +19,12 @@ import java.util.List;
|
||||
public interface JsonSchemaService {
|
||||
|
||||
class Impl {
|
||||
|
||||
@Nullable
|
||||
public static JsonSchemaService get(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, JsonSchemaService.class);
|
||||
}
|
||||
|
||||
public static JsonSchemaServiceEx getEx(@NotNull Project project) {
|
||||
return (JsonSchemaServiceEx) ServiceManager.getService(project, JsonSchemaService.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -15,16 +15,17 @@
|
||||
*/
|
||||
package com.jetbrains.jsonSchema.impl;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.PairConsumer;
|
||||
import com.intellij.util.containers.BidirectionalMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.jetbrains.jsonSchema.extension.JsonSchemaProjectSelfProviderFactory;
|
||||
import com.jetbrains.jsonSchema.extension.SchemaType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static com.jetbrains.jsonSchema.impl.JsonSchemaReader.LOG;
|
||||
@@ -39,12 +40,9 @@ public class JsonSchemaExportedDefinitions {
|
||||
private final BidirectionalMap<String, Pair<SchemaType, ?>> myId2Key;
|
||||
private final MultiMap<Pair<SchemaType, ?>, Pair<SchemaType, ?>> myCrossDependencies;
|
||||
private final Map<String, Map<String, JsonSchemaObject>> myMap;
|
||||
private final Project myProject;
|
||||
@NotNull private final Consumer<PairConsumer<Pair<SchemaType, ?>, Consumer<Consumer<JsonSchemaObject>>>> mySchemasIterator;
|
||||
|
||||
public JsonSchemaExportedDefinitions(@Nullable final Project project,
|
||||
@NotNull Consumer<PairConsumer<Pair<SchemaType, ?>, Consumer<Consumer<JsonSchemaObject>>>> schemasIterator) {
|
||||
myProject = project;
|
||||
public JsonSchemaExportedDefinitions(@NotNull Consumer<PairConsumer<Pair<SchemaType, ?>, Consumer<Consumer<JsonSchemaObject>>>> schemasIterator) {
|
||||
mySchemasIterator = schemasIterator;
|
||||
myLock = new Object();
|
||||
myMap = new HashMap<>();
|
||||
@@ -131,4 +129,19 @@ public class JsonSchemaExportedDefinitions {
|
||||
}
|
||||
return dirtyKeys;
|
||||
}
|
||||
|
||||
public boolean checkFileForId(@NotNull final String id, @NotNull final VirtualFile file) {
|
||||
final Pair<SchemaType, ?> pair;
|
||||
synchronized (myLock) {
|
||||
ensureInitialized();
|
||||
pair = myId2Key.get(id);
|
||||
}
|
||||
if (pair == null) return false;
|
||||
if (SchemaType.schema.equals(pair.getFirst())) return JsonSchemaProjectSelfProviderFactory.SCHEMA_JSON_FILE_NAME
|
||||
.equals(file.getName());
|
||||
if (SchemaType.embeddedSchema.equals(pair.getFirst())) return file.getName().equals(pair.getSecond());
|
||||
if (SchemaType.userSchema.equals(pair.getFirst())) return pair.getSecond() != null &&
|
||||
pair.getSecond().equals(new File(file.getPath()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.Map;
|
||||
/**
|
||||
* @author Irina.Chernushina on 8/28/2015.
|
||||
*/
|
||||
class JsonSchemaObject {
|
||||
public class JsonSchemaObject {
|
||||
private Map<String, JsonSchemaObject> myDefinitions;
|
||||
private Map<String, JsonSchemaObject> myProperties;
|
||||
private Map<String, JsonSchemaObject> myPatternProperties;
|
||||
|
||||
@@ -162,7 +162,7 @@ public class JsonSchemaReader {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static JsonSchemaObject findDefinition(@NotNull Pair<SchemaType, ?> key,
|
||||
public static JsonSchemaObject findDefinition(@NotNull Pair<SchemaType, ?> key,
|
||||
@NotNull String ref,
|
||||
@NotNull final JsonSchemaObject root,
|
||||
@NotNull final Map<String, JsonSchemaObject> ids,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.vfs.VirtualFile;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 4/1/2016.
|
||||
*/
|
||||
public interface JsonSchemaServiceEx extends JsonSchemaService {
|
||||
|
||||
boolean checkFileForId(@NotNull String id, @NotNull VirtualFile file);
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import com.jetbrains.jsonSchema.extension.JsonSchemaFileProvider;
|
||||
import com.jetbrains.jsonSchema.extension.JsonSchemaImportedProviderMarker;
|
||||
import com.jetbrains.jsonSchema.extension.JsonSchemaProviderFactory;
|
||||
import com.jetbrains.jsonSchema.extension.SchemaType;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -38,7 +37,7 @@ import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.*;
|
||||
|
||||
public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
public class JsonSchemaServiceImpl implements JsonSchemaServiceEx {
|
||||
private static final Logger LOGGER = Logger.getInstance(JsonSchemaServiceImpl.class);
|
||||
private static final Logger RARE_LOGGER = RareLogger.wrap(LOGGER, false);
|
||||
@Nullable
|
||||
@@ -50,8 +49,8 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
public JsonSchemaServiceImpl(@Nullable Project project) {
|
||||
myLock = new Object();
|
||||
myProject = project;
|
||||
myDefinitions = new JsonSchemaExportedDefinitions(project,
|
||||
new Consumer<PairConsumer<Pair<SchemaType, ?>, Consumer<Consumer<JsonSchemaObject>>>>() {
|
||||
myDefinitions = new JsonSchemaExportedDefinitions(
|
||||
new Consumer<PairConsumer<Pair<SchemaType, ?>, Consumer<Consumer<JsonSchemaObject>>>>() {
|
||||
@Override
|
||||
public void consume(PairConsumer<Pair<SchemaType, ?>, Consumer<Consumer<JsonSchemaObject>>> consumer) {
|
||||
iterateSchemas(consumer);
|
||||
@@ -147,6 +146,13 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
}
|
||||
catch (Exception e) {
|
||||
logException(provider, e);
|
||||
} finally {
|
||||
if (reader != null) try {
|
||||
reader.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
logException(provider, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -303,4 +309,9 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
return myDocumentationProvider;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkFileForId(@NotNull final String id, @NotNull final VirtualFile file) {
|
||||
return myDefinitions.checkFileForId(id, file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,15 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.extensions.AreaPicoContainer;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import com.jetbrains.jsonSchema.schemaFile.TestJsonSchemaMappingsProjectConfiguration;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -33,6 +39,15 @@ import java.util.Collections;
|
||||
*/
|
||||
public class JsonSchemaCrossReferencesTest extends CompletionTestCase {
|
||||
private final static String BASE_PATH = "/tests/testData/jsonSchema/crossReferences";
|
||||
private final static String BASE_SCHEMA_RESOLVE_PATH = "/tests/testData/jsonSchema/schemaFile/resolve";
|
||||
|
||||
private FileTypeManager myFileTypeManager;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFileTypeManager = FileTypeManager.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
@@ -173,4 +188,63 @@ public class JsonSchemaCrossReferencesTest extends CompletionTestCase {
|
||||
complete();
|
||||
assertStringItems("\"one1\"", "\"two1\"");
|
||||
}
|
||||
|
||||
public void testJsonSchemaRefsCrossResolve() throws Exception {
|
||||
configureByFiles(null, BASE_SCHEMA_RESOLVE_PATH + "/referencingSchema.json", BASE_SCHEMA_RESOLVE_PATH + "/localRefSchema.json");
|
||||
|
||||
String moduleDir = null;
|
||||
VirtualFile moduleFile = null;
|
||||
VirtualFile[] children = getProject().getBaseDir().getChildren();
|
||||
for (VirtualFile child : children) {
|
||||
if (child.isDirectory()) {
|
||||
moduleDir = child.getName();
|
||||
moduleFile = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.assertNotNull(moduleDir);
|
||||
|
||||
AreaPicoContainer container = Extensions.getArea(getProject()).getPicoContainer();
|
||||
final String key = JsonSchemaMappingsProjectConfiguration.class.getName();
|
||||
container.unregisterComponent(key);
|
||||
container.registerComponentImplementation(key, TestJsonSchemaMappingsProjectConfiguration.class);
|
||||
|
||||
final JsonSchemaMappingsProjectConfiguration instance = JsonSchemaMappingsProjectConfiguration.getInstance(getProject());
|
||||
final JsonSchemaMappingsConfigurationBase.SchemaInfo base =
|
||||
new JsonSchemaMappingsConfigurationBase.SchemaInfo("base", "/" + moduleDir + "/localRefSchema.json", false, Collections.emptyList());
|
||||
instance.addSchema(base);
|
||||
|
||||
final JsonSchemaMappingsConfigurationBase.SchemaInfo inherited
|
||||
= new JsonSchemaMappingsConfigurationBase.SchemaInfo("inherited", "/" + moduleDir + "/referencingSchema.json", false, Collections.emptyList());
|
||||
|
||||
instance.addSchema(inherited);
|
||||
|
||||
try {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myFileTypeManager.associatePattern(JsonSchemaFileType.INSTANCE, "*Schema.json");
|
||||
}
|
||||
});
|
||||
int offset = myEditor.getCaretModel().getPrimaryCaret().getOffset();
|
||||
final PsiReference referenceAt = myFile.findReferenceAt(offset);
|
||||
Assert.assertNotNull(referenceAt);
|
||||
final PsiElement resolve = referenceAt.resolve();
|
||||
Assert.assertNotNull(resolve);
|
||||
Assert.assertEquals("\"baseEnum\"", resolve.getText());
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myFileTypeManager.removeAssociatedExtension(JsonSchemaFileType.INSTANCE, "*Schema.json");
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
container.unregisterComponent(key);
|
||||
container.registerComponentImplementation(key, JsonSchemaMappingsProjectConfiguration.class);
|
||||
}
|
||||
|
||||
instance.removeSchema(inherited);
|
||||
instance.removeSchema(base);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.jetbrains.jsonSchema;
|
||||
|
||||
|
||||
import com.intellij.json.JsonFileType;
|
||||
import com.intellij.json.JsonLanguage;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.jsonSchema.extension.JsonSchemaFileProvider;
|
||||
@@ -22,7 +23,7 @@ public class JsonSchemaTestProvider implements JsonSchemaFileProvider<String> {
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull VirtualFile file) {
|
||||
return file.getFileType() == JsonFileType.INSTANCE;
|
||||
return file.getFileType() instanceof LanguageFileType && ((LanguageFileType)file.getFileType()).getLanguage().isKindOf(JsonLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.schemaFile;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.extensions.AreaPicoContainer;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
|
||||
import com.jetbrains.jsonSchema.JsonSchemaFileType;
|
||||
import com.jetbrains.jsonSchema.JsonSchemaMappingsProjectConfiguration;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 4/1/2016.
|
||||
*/
|
||||
public class JsonSchemaFileResolveTest extends LightPlatformCodeInsightFixtureTestCase {
|
||||
private final static String BASE_PATH = "/tests/testData/jsonSchema/schemaFile/resolve";
|
||||
private FileTypeManager myFileTypeManager;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFileTypeManager = FileTypeManagerEx.getInstanceEx();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
PathManagerEx.TestDataLookupStrategy strategy = PathManagerEx.guessTestDataLookupStrategy();
|
||||
if (strategy.equals(PathManagerEx.TestDataLookupStrategy.COMMUNITY)) {
|
||||
return PathManager.getHomePath() + "/json" + BASE_PATH;
|
||||
}
|
||||
return PathManager.getHomePath() + "/community/json" + BASE_PATH;
|
||||
}
|
||||
|
||||
public void testResolveLocalRef() throws Exception {
|
||||
AreaPicoContainer container = Extensions.getArea(getProject()).getPicoContainer();
|
||||
final String key = JsonSchemaMappingsProjectConfiguration.class.getName();
|
||||
container.unregisterComponent(key);
|
||||
container.registerComponentImplementation(key, TestJsonSchemaMappingsProjectConfiguration.class);
|
||||
|
||||
try {
|
||||
myFileTypeManager.associatePattern(JsonSchemaFileType.INSTANCE, "*Schema.json");
|
||||
PsiReference position = myFixture.getReferenceAtCaretPosition("localRefSchema.json");
|
||||
Assert.assertNotNull(position);
|
||||
PsiElement resolve = position.resolve();
|
||||
Assert.assertNotNull(resolve);
|
||||
Assert.assertEquals("\"baseEnum\"", resolve.getText());
|
||||
|
||||
myFileTypeManager.removeAssociatedExtension(JsonSchemaFileType.INSTANCE, "*Schema.json");
|
||||
} finally {
|
||||
container.unregisterComponent(key);
|
||||
container.registerComponentImplementation(key, JsonSchemaMappingsProjectConfiguration.class);
|
||||
}
|
||||
}
|
||||
|
||||
public void testResolveExternalRef() throws Exception {
|
||||
AreaPicoContainer container = Extensions.getArea(getProject()).getPicoContainer();
|
||||
final String key = JsonSchemaMappingsProjectConfiguration.class.getName();
|
||||
container.unregisterComponent(key);
|
||||
container.registerComponentImplementation(key, TestJsonSchemaMappingsProjectConfiguration.class);
|
||||
|
||||
try {
|
||||
myFileTypeManager.associatePattern(JsonSchemaFileType.INSTANCE, "*Schema.json");
|
||||
PsiReference position = myFixture.getReferenceAtCaretPosition("localRefSchema.json");
|
||||
Assert.assertNotNull(position);
|
||||
PsiElement resolve = position.resolve();
|
||||
Assert.assertNotNull(resolve);
|
||||
Assert.assertEquals("\"baseEnum\"", resolve.getText());
|
||||
|
||||
myFileTypeManager.removeAssociatedExtension(JsonSchemaFileType.INSTANCE, "*Schema.json");
|
||||
} finally {
|
||||
container.unregisterComponent(key);
|
||||
container.registerComponentImplementation(key, JsonSchemaMappingsProjectConfiguration.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
@@ -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.schemaFile;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.jsonSchema.JsonSchemaMappingsProjectConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Irina.Chernushina on 4/1/2016.
|
||||
*/
|
||||
public class TestJsonSchemaMappingsProjectConfiguration extends JsonSchemaMappingsProjectConfiguration {
|
||||
public TestJsonSchemaMappingsProjectConfiguration(Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisteredSchemaFile(@NotNull VirtualFile file) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "https://myurl",
|
||||
"properties": {
|
||||
"baseEnum": {
|
||||
"type": "string",
|
||||
"enum": ["one", "two"]
|
||||
},
|
||||
"smth": {
|
||||
"$ref" : "#/properties/baseEnum<caret>"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"smth": {
|
||||
"$ref" : "https://myurl#/properties/baseEnum<caret>"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<fileTypeFactory implementation="com.intellij.json.JsonFileTypeFactory"/>
|
||||
<fileTypeFactory implementation="com.jetbrains.jsonSchema.JsonSchemaFileTypeFactory"/>
|
||||
<lang.parserDefinition language="JSON" implementationClass="com.intellij.json.JsonParserDefinition"/>
|
||||
<lang.syntaxHighlighterFactory language="JSON" implementationClass="com.intellij.json.highlighting.JsonSyntaxHighlighterFactory"/>
|
||||
<psi.treeChangePreprocessor implementation="com.intellij.json.psi.impl.JsonTreeChangePreprocessor"/>
|
||||
@@ -73,6 +74,9 @@
|
||||
<refactoring.elementListenerProvider implementation="com.jetbrains.jsonSchema.JsonSchemaRefactoringListenerProvider"/>
|
||||
<editorNotificationProvider implementation="com.jetbrains.jsonSchema.impl.JsonSchemaConflictNotificationProvider"/>
|
||||
<projectService serviceImplementation="com.jetbrains.jsonSchema.extension.JsonSchemaProjectSelfProviderFactory"/>
|
||||
|
||||
<fileBasedIndex implementation="com.jetbrains.jsonSchema.extension.schema.JsonSchemaFileIndex"/>
|
||||
<psi.referenceContributor language="JSON" implementation="com.jetbrains.jsonSchema.extension.schema.JsonSchemaReferenceContributor"/>
|
||||
</extensions>
|
||||
<extensions defaultExtensionNs="JavaScript">
|
||||
<JsonSchema.ProviderFactory implementation="com.jetbrains.jsonSchema.extension.JsonSchemaImportedProviderFactory"/>
|
||||
|
||||
Reference in New Issue
Block a user