Problem
The JsonConstructionCache used in DefaultPsiClassHelper.buildTypeObject() is local to a single buildObjectModel call. When the same type (e.g., UserInfo) appears as a request body in one endpoint and as a response body in another, the entire ObjectModel is rebuilt from scratch — including recursive type resolution, field extraction, and rule evaluation for every field.
For example, if ResponseEntity<UserInfo> is the return type of 20 endpoints, UserInfo's ObjectModel is built 20 times.
Impact
For projects with shared DTOs used across many endpoints, this causes significant redundant work. Each ObjectModel build involves:
- PSI class resolution
- Generic type substitution
- Rule evaluation for every field (
FIELD_IGNORE, FIELD_NAME, FIELD_DOC, FIELD_REQUIRED, FIELD_DEFAULT_VALUE, FIELD_MOCK, FIELD_DEMO, FIELD_ADVANCED, JSON_RULE_CONVERT)
- Recursive processing of nested types
Estimated speedup: 1.2-1.5x for projects with repeated types
Fix
Introduce a project-level or scan-session-level cache keyed by (qualifiedName, option) that persists across buildObjectModel calls:
@Service(Service.Level.PROJECT)
class DefaultPsiClassHelper(private val project: Project) : PsiClassHelper {
private val modelCache = ConcurrentHashMap<String, ObjectModel?>()
override suspend fun buildObjectModel(
psiClass: PsiClass,
option: Int,
maxDepth: Int
): ObjectModel? {
val qualifiedName = psiClass.qualifiedName ?: return null
val cacheKey = "$qualifiedName@$option"
modelCache[cacheKey]?.let { return it }
val result = buildTypeObject(psiClass, ...)
if (result != null) {
modelCache[cacheKey] = result
}
return result
}
}
The cache should be invalidated when source files change (can hook into ApiFileChangeListener).
Location
src/main/kotlin/com/itangcent/easyapi/psi/DefaultPsiClassHelper.kt:98-127
Problem
The
JsonConstructionCacheused inDefaultPsiClassHelper.buildTypeObject()is local to a singlebuildObjectModelcall. When the same type (e.g.,UserInfo) appears as a request body in one endpoint and as a response body in another, the entire ObjectModel is rebuilt from scratch — including recursive type resolution, field extraction, and rule evaluation for every field.For example, if
ResponseEntity<UserInfo>is the return type of 20 endpoints,UserInfo's ObjectModel is built 20 times.Impact
For projects with shared DTOs used across many endpoints, this causes significant redundant work. Each ObjectModel build involves:
FIELD_IGNORE,FIELD_NAME,FIELD_DOC,FIELD_REQUIRED,FIELD_DEFAULT_VALUE,FIELD_MOCK,FIELD_DEMO,FIELD_ADVANCED,JSON_RULE_CONVERT)Estimated speedup: 1.2-1.5x for projects with repeated types
Fix
Introduce a project-level or scan-session-level cache keyed by
(qualifiedName, option)that persists acrossbuildObjectModelcalls:The cache should be invalidated when source files change (can hook into
ApiFileChangeListener).Location
src/main/kotlin/com/itangcent/easyapi/psi/DefaultPsiClassHelper.kt:98-127