[json] IJPL-156923 Cache element validity against a particular schema node to avoid double computation

With the introduction of if-then-else resolve that selects a branch depending on a given instance file element, the number of calls to JsonSchemaResolver.isCorrect method increased significantly. It is expected, as any validation/reference contribution/other editor features require a resolved schema node.

Resolve results are cached on language modification tracker because with the instance file updates, a previously valid if-else branch might become invalid

GitOrigin-RevId: f197203a3c53a7c4e7c1d502faaff3d50a9451e3
This commit is contained in:
Nikita Katkov
2024-06-27 14:32:27 +02:00
committed by intellij-monorepo-bot
parent b0e1b50725
commit 86e193d79f
2 changed files with 44 additions and 4 deletions

View File

@@ -24,13 +24,14 @@ import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import static com.jetbrains.jsonSchema.impl.JsonSchemaValidityCacheKt.getOrComputeAdapterValidityAgainstGivenSchema;
import static com.jetbrains.jsonSchema.impl.light.SchemaKeywordsKt.*;
public final class JsonSchemaResolver {
private final @NotNull Project myProject;
private final @NotNull JsonSchemaObject mySchema;
private final @NotNull JsonPointerPosition myPosition;
private final @Nullable JsonSchemaNodeExpansionRequest myExpansionRequest;
private final @NotNull JsonSchemaNodeExpansionRequest myExpansionRequest;
/**
@@ -209,8 +210,6 @@ public final class JsonSchemaResolver {
}
public static boolean isCorrect(final @NotNull JsonValueAdapter value, final @NotNull JsonSchemaObject schema) {
final JsonSchemaAnnotatorChecker checker = new JsonSchemaAnnotatorChecker(value.getDelegate().getProject(), JsonComplianceCheckerOptions.RELAX_ENUM_CHECK);
checker.checkByScheme(value, schema);
return checker.isCorrect();
return getOrComputeAdapterValidityAgainstGivenSchema(value, schema);
}
}

View File

@@ -0,0 +1,41 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.jsonSchema.impl
import com.intellij.openapi.util.Key
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.jetbrains.jsonSchema.extension.adapters.JsonValueAdapter
import com.jetbrains.jsonSchema.ide.JsonSchemaService
import java.util.concurrent.ConcurrentHashMap
private val JSON_SCHEMA_VALIDATION_MAP = Key.create<CachedValue<MutableMap<JsonSchemaObject, Boolean>>>("JSON_SCHEMA_VALIDATION_MAP")
internal fun getOrComputeAdapterValidityAgainstGivenSchema(value: JsonValueAdapter, schema: JsonSchemaObject): Boolean {
val delegatePsi = value.delegate
val cachedMap: MutableMap<JsonSchemaObject, Boolean> =
CachedValuesManager.getManager(delegatePsi.project).getCachedValue(
delegatePsi,
JSON_SCHEMA_VALIDATION_MAP,
CachedValueProvider {
CachedValueProvider.Result.create(
ConcurrentHashMap(),
delegatePsi.manager.modificationTracker.forLanguage(delegatePsi.language),
JsonSchemaService.Impl.get(delegatePsi.project)
)
},
false
)
val cachedValue = cachedMap[schema]
if (cachedValue != null) {
return cachedValue
}
val checker = JsonSchemaAnnotatorChecker(value.delegate.project, JsonComplianceCheckerOptions.RELAX_ENUM_CHECK)
checker.checkByScheme(value, schema)
val computedValue = checker.isCorrect
cachedMap[schema] = computedValue
return computedValue
}