mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
json schema performance: cache computed json schema for a psi file, don't recompute it every time
this fixes performance tests after adding the injection feature injection checks are invoked for every matching-by-class psi element, and that is really expensive if to recompute
This commit is contained in:
@@ -57,7 +57,7 @@ public class JsonSpellcheckerStrategy extends SpellcheckingStrategy {
|
||||
Project project = element.getProject();
|
||||
final JsonSchemaService service = JsonSchemaService.Impl.get(project);
|
||||
if (!service.isApplicableToFile(file)) return false;
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(file);
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(element.getContainingFile());
|
||||
if (rootSchema == null) return false;
|
||||
if (service.isSchemaFile(rootSchema)) {
|
||||
JsonProperty property = ObjectUtils.tryCast(element.getParent(), JsonProperty.class);
|
||||
|
||||
@@ -54,6 +54,9 @@ public interface JsonSchemaService {
|
||||
@Nullable
|
||||
JsonSchemaObject getSchemaObject(@NotNull VirtualFile file);
|
||||
|
||||
@Nullable
|
||||
JsonSchemaObject getSchemaObject(@NotNull PsiFile file);
|
||||
|
||||
@Nullable
|
||||
JsonSchemaObject getSchemaObjectForSchemaFile(@NotNull VirtualFile schemaFile);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 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;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionUtil;
|
||||
import com.intellij.json.navigation.JsonQualifiedNameKind;
|
||||
import com.intellij.json.navigation.JsonQualifiedNameProvider;
|
||||
import com.intellij.json.psi.*;
|
||||
@@ -20,6 +21,7 @@ import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.jsonSchema.JsonPointerUtil;
|
||||
import com.jetbrains.jsonSchema.JsonSchemaCatalogEntry;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
import com.jetbrains.jsonSchema.remote.JsonFileResolver;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -207,4 +209,21 @@ public class JsonCachedValues {
|
||||
@NotNull Key<CachedValue<T>> key) {
|
||||
return CachedValuesManager.getCachedValue(psiFile, key, () -> CachedValueProvider.Result.create(eval.fun(psiFile), psiFile));
|
||||
}
|
||||
|
||||
public static final Key<CachedValue<JsonSchemaObject>> OBJECT_FOR_FILE_KEY = new Key<>("JsonCachedValues.OBJ_KEY");
|
||||
@Nullable
|
||||
static JsonSchemaObject computeSchemaForFile(@NotNull PsiFile file, @NotNull JsonSchemaService service) {
|
||||
final PsiFile originalFile = CompletionUtil.getOriginalOrSelf(file);
|
||||
JsonSchemaObject value = CachedValuesManager.getCachedValue(originalFile, OBJECT_FOR_FILE_KEY, () -> {
|
||||
VirtualFile virtualFile = originalFile.getVirtualFile();
|
||||
JsonSchemaObject schemaObject = virtualFile == null ? null : service.getSchemaObject(virtualFile);
|
||||
VirtualFile schemaFile = schemaObject == null ? null : service.resolveSchemaFile(schemaObject);
|
||||
PsiFile psiFile = schemaFile == null ? null : originalFile.getManager().findFile(schemaFile);
|
||||
JsonSchemaObject object = schemaObject == null ? JsonSchemaObject.NULL_OBJ : schemaObject;
|
||||
return psiFile == null
|
||||
? CachedValueProvider.Result.create(object, originalFile)
|
||||
: CachedValueProvider.Result.create(object, originalFile, psiFile);
|
||||
});
|
||||
return value == JsonSchemaObject.NULL_OBJ ? null : value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import com.intellij.json.psi.JsonStringLiteral;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.injection.MultiHostRegistrar;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.jetbrains.jsonSchema.extension.JsonLikePsiWalker;
|
||||
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
|
||||
@@ -28,9 +28,8 @@ public class JsonSchemaBasedLanguageInjector extends JsonSchemaInjectorBase {
|
||||
@Nullable
|
||||
public static Language getLanguageToInject(@NotNull PsiElement context) {
|
||||
Project project = context.getProject();
|
||||
VirtualFile file = context.getContainingFile().getVirtualFile();
|
||||
if (file == null) return null;
|
||||
JsonSchemaObject schemaObject = JsonSchemaService.Impl.get(project).getSchemaObject(file);
|
||||
PsiFile containingFile = context.getContainingFile();
|
||||
JsonSchemaObject schemaObject = JsonSchemaService.Impl.get(project).getSchemaObject(containingFile);
|
||||
if (schemaObject == null) return null;
|
||||
JsonLikePsiWalker walker = JsonLikePsiWalker.getWalker(context, schemaObject);
|
||||
if (walker == null || walker.isName(context) != ThreeState.NO) return null;
|
||||
|
||||
@@ -68,7 +68,7 @@ public class JsonSchemaCompletionContributor extends CompletionContributor {
|
||||
|
||||
final JsonSchemaService service = JsonSchemaService.Impl.get(position.getProject());
|
||||
if (!service.isApplicableToFile(file)) return;
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(file);
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(position.getContainingFile());
|
||||
if (rootSchema == null) return;
|
||||
PsiElement positionParent = position.getParent();
|
||||
if (positionParent != null) {
|
||||
|
||||
@@ -59,7 +59,7 @@ public class JsonSchemaDocumentationProvider implements DocumentationProvider {
|
||||
final JsonSchemaService service = JsonSchemaService.Impl.get(element.getProject());
|
||||
VirtualFile virtualFile = containingFile.getViewProvider().getVirtualFile();
|
||||
if (!service.isApplicableToFile(virtualFile)) return null;
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(virtualFile);
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(containingFile);
|
||||
if (rootSchema == null) return null;
|
||||
|
||||
return generateDoc(element, rootSchema, preferShort, forcedPropName);
|
||||
|
||||
@@ -32,7 +32,7 @@ public class JsonSchemaGotoDeclarationHandler implements GotoDeclarationHandler
|
||||
if (file == null || !service.isApplicableToFile(file)) return null;
|
||||
final JsonPointerPosition steps = JsonOriginalPsiWalker.INSTANCE.findPosition(literal, true);
|
||||
if (steps == null) return null;
|
||||
final JsonSchemaObject schemaObject = service.getSchemaObject(file);
|
||||
final JsonSchemaObject schemaObject = service.getSchemaObject(containingFile);
|
||||
if (schemaObject != null) {
|
||||
final PsiElement target = new JsonSchemaResolver(sourceElement.getProject(), schemaObject, steps).findNavigationTarget(((JsonProperty)parent).getValue());
|
||||
if (target != null) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.containers.ConcurrentList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
@@ -285,6 +286,13 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
return JsonCachedValues.getSchemaObject(replaceHttpFileWithBuiltinIfNeeded(schemaFile), myProject);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JsonSchemaObject getSchemaObject(@NotNull PsiFile file) {
|
||||
return JsonCachedValues.computeSchemaForFile(file, this);
|
||||
}
|
||||
|
||||
public VirtualFile replaceHttpFileWithBuiltinIfNeeded(VirtualFile schemaFile) {
|
||||
// this hack is needed to handle user-defined mappings via urls
|
||||
// we cannot perform that inside corresponding provider, because it leads to recursive component dependency
|
||||
@@ -460,8 +468,9 @@ public class JsonSchemaServiceImpl implements JsonSchemaService {
|
||||
@NotNull
|
||||
@Override
|
||||
public MultiMap<VirtualFile, JsonSchemaFileProvider> compute() {
|
||||
MultiMap<VirtualFile, JsonSchemaFileProvider> map = createFileProviderMap(myFactory.create(), myProject);
|
||||
myIsComputed.set(true);
|
||||
return createFileProviderMap(myFactory.create(), myProject);
|
||||
return map;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ public abstract class JsonSchemaBasedInspectionBase extends LocalInspectionTool
|
||||
VirtualFile virtualFile = file.getViewProvider().getVirtualFile();
|
||||
if (!service.isApplicableToFile(virtualFile)) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
|
||||
return doBuildVisitor(root, service.getSchemaObject(virtualFile), service, holder, session);
|
||||
return doBuildVisitor(root, service.getSchemaObject(file), service, holder, session);
|
||||
}
|
||||
|
||||
protected abstract PsiElementVisitor doBuildVisitor(@NotNull JsonValue root,
|
||||
|
||||
@@ -819,11 +819,11 @@ public class JsonSchemaCrossReferencesTest extends JsonSchemaHeavyAbstractTest {
|
||||
@Override
|
||||
public void configureFiles() {
|
||||
configureByFiles(null, "completionWithRootRef.json", "cycledWithRootRefSchema.json");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCheck() {
|
||||
complete();
|
||||
checkCompletion("\"id\"", "\"testProp\"");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -28,11 +28,11 @@ public class JsonSchemaPerformanceTest extends JsonSchemaHeavyAbstractTest {
|
||||
}
|
||||
|
||||
public void testSwaggerHighlighting() {
|
||||
doPerformanceTest(10000, "swagger");
|
||||
doPerformanceTest(8000, "swagger");
|
||||
}
|
||||
|
||||
public void testTsLintSchema() {
|
||||
doPerformanceTest(9000, "tslint-schema");
|
||||
doPerformanceTest(7500, "tslint-schema");
|
||||
}
|
||||
|
||||
private void doPerformanceTest(int expectedMs, String jsonFileNameWithoutExtension) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class JsonSchemaTestServiceImpl extends JsonSchemaServiceImpl {
|
||||
private static JsonSchemaFileProvider provider;
|
||||
@@ -36,4 +37,15 @@ public final class JsonSchemaTestServiceImpl extends JsonSchemaServiceImpl {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(JsonSchemaTestServiceImpl.class, "test");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof JsonSchemaTestServiceImpl) return true;
|
||||
return super.equals(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class YamlJsonSchemaCompletionContributor extends CompletionContributor {
|
||||
public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
final JsonSchemaService jsonSchemaService = JsonSchemaService.Impl.get(position.getProject());
|
||||
JsonSchemaObject object = jsonSchemaService.getSchemaObject(parameters.getOriginalFile().getVirtualFile());
|
||||
JsonSchemaObject object = jsonSchemaService.getSchemaObject(parameters.getOriginalFile());
|
||||
if (object != null) {
|
||||
JsonSchemaCompletionContributor.doCompletion(parameters, result, object, false);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.jetbrains.yaml.schema;
|
||||
|
||||
import com.intellij.lang.documentation.DocumentationProviderEx;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
@@ -39,9 +38,7 @@ public class YamlJsonSchemaDocumentationProvider extends DocumentationProviderEx
|
||||
final JsonSchemaService jsonSchemaService = JsonSchemaService.Impl.get(element.getProject());
|
||||
PsiFile containingFile = element.getContainingFile();
|
||||
if (containingFile == null) return null;
|
||||
VirtualFile virtualFile = containingFile.getVirtualFile();
|
||||
if (virtualFile == null) return null;
|
||||
JsonSchemaObject schemaObject = jsonSchemaService.getSchemaObject(virtualFile);
|
||||
JsonSchemaObject schemaObject = jsonSchemaService.getSchemaObject(containingFile);
|
||||
if (schemaObject == null) return null;
|
||||
return JsonSchemaDocumentationProvider.generateDoc(element, schemaObject, preferShort, null);
|
||||
}
|
||||
@@ -64,8 +61,7 @@ public class YamlJsonSchemaDocumentationProvider extends DocumentationProviderEx
|
||||
@NotNull PsiFile file,
|
||||
@Nullable PsiElement contextElement) {
|
||||
JsonSchemaService service = JsonSchemaService.Impl.get(file.getProject());
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile == null || service == null || service.getSchemaObject(virtualFile) == null) return null;
|
||||
if (service == null || service.getSchemaObject(file) == null) return null;
|
||||
return contextElement;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class YamlJsonSchemaGotoDeclarationHandler implements GotoDeclarationHand
|
||||
if (file == null || !service.isApplicableToFile(file)) return null;
|
||||
final JsonPointerPosition steps = YamlJsonPsiWalker.INSTANCE.findPosition(literal, true);
|
||||
if (steps == null) return null;
|
||||
final JsonSchemaObject schemaObject = service.getSchemaObject(file);
|
||||
final JsonSchemaObject schemaObject = service.getSchemaObject(containingFile);
|
||||
if (schemaObject != null) {
|
||||
final PsiElement target = new JsonSchemaResolver(sourceElement.getProject(), schemaObject, steps).findNavigationTarget(literal.getValue());
|
||||
if (target != null) {
|
||||
|
||||
@@ -33,16 +33,11 @@ public abstract class YamlJsonSchemaInspectionBase extends LocalInspectionTool {
|
||||
if (!service.isApplicableToFile(virtualFile)) {
|
||||
return PsiElementVisitor.EMPTY_VISITOR;
|
||||
}
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(virtualFile);
|
||||
final JsonSchemaObject rootSchema = service.getSchemaObject(file);
|
||||
if (rootSchema == null) {
|
||||
return PsiElementVisitor.EMPTY_VISITOR;
|
||||
}
|
||||
|
||||
JsonSchemaObject object = service.getSchemaObject(virtualFile);
|
||||
if (object == null) {
|
||||
return PsiElementVisitor.EMPTY_VISITOR;
|
||||
}
|
||||
return doBuildVisitor(holder, session, root, object);
|
||||
return doBuildVisitor(holder, session, root, rootSchema);
|
||||
}
|
||||
|
||||
protected abstract PsiElementVisitor doBuildVisitor(@NotNull ProblemsHolder holder,
|
||||
|
||||
Reference in New Issue
Block a user