private static MultiHostRegistrarImpl probeElementsUp(@NotNull PsiElement element, @NotNull PsiFile hostPsiFile, boolean probeUp) { PsiManager psiManager = hostPsiFile.getManager(); final Project project = psiManager.getProject(); InjectedLanguageManagerImpl injectedManager = InjectedLanguageManagerImpl.getInstanceImpl(project); if (injectedManager == null) { return null; //for tests } MultiHostRegistrarImpl registrar = null; PsiElement current = element; nextParent: while (current != null && current != hostPsiFile && !(current instanceof PsiDirectory)) { ProgressManager.checkCanceled(); if ("EL".equals(current.getLanguage().getID())) break; ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> data = current.getUserData(INJECTED_PSI); if (data == null) { registrar = InjectedPsiCachedValueProvider.doCompute(current, injectedManager, project, hostPsiFile); } else { registrar = data.getValue(current); } current = current.getParent(); // cache no injection for current if (registrar != null) { List<Pair<Place, PsiFile>> places = registrar.getResult(); // check that injections found intersect with queried element TextRange elementRange = element.getTextRange(); for (Pair<Place, PsiFile> pair : places) { Place place = pair.first; for (PsiLanguageInjectionHost.Shred shred : place) { if (shred.getHost().getTextRange().intersects(elementRange)) { if (place.isValid()) break nextParent; } } } } if (!probeUp) { break; } } if (probeUp) { // cache only if we walked all parents for (PsiElement e = element; e != current && e != null && e != hostPsiFile; e = e.getParent()) { ProgressManager.checkCanceled(); if (registrar == null) { e.putUserData(INJECTED_PSI, null); } else { ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> cachedValue = CachedValuesManager.getManager(project).createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false); CachedValueProvider.Result<MultiHostRegistrarImpl> result = CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar); ((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>)cachedValue).setValue(result); e.putUserData(INJECTED_PSI, cachedValue); } } } return registrar; }
private static MultiHostRegistrarImpl probeElementsUp(@NotNull PsiElement element, @NotNull PsiFile hostPsiFile, boolean probeUp) { PsiManager psiManager = hostPsiFile.getManager(); final Project project = psiManager.getProject(); InjectedLanguageManagerImpl injectedManager = InjectedLanguageManagerImpl.getInstanceImpl(project); if (injectedManager == null) { return null; //for tests } MultiHostRegistrarImpl registrar = null; PsiElement current = element; nextParent: while (current != null && current != hostPsiFile) { ProgressManager.checkCanceled(); if ("EL".equals(current.getLanguage().getID())) break; ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> data = current.getUserData(INJECTED_PSI); if (data == null) { registrar = InjectedPsiCachedValueProvider.doCompute(current, injectedManager, project, hostPsiFile); } else { registrar = data.getValue(current); } current = current.getParent(); // cache no injection for current if (registrar != null) { List<Pair<Place, PsiFile>> places = registrar.getResult(); // check that injections found intersect with queried element TextRange elementRange = element.getTextRange(); for (Pair<Place, PsiFile> pair : places) { Place place = pair.first; for (PsiLanguageInjectionHost.Shred shred : place) { if (shred.getHost().getTextRange().intersects(elementRange)) { if (place.isValid()) break nextParent; } } } } if (!probeUp) { break; } } if (probeUp) { // cache only if we walked all parents for (PsiElement e = element; e != current && e != null && e != hostPsiFile; e = e.getParent()) { ProgressManager.checkCanceled(); if (registrar == null) { e.putUserData(INJECTED_PSI, null); } else { ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> cachedValue = CachedValuesManager.getManager(project).createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false); CachedValueProvider.Result<MultiHostRegistrarImpl> result = CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar); ((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>)cachedValue).setValue(result); e.putUserData(INJECTED_PSI, cachedValue); } } } return registrar; }
@Override public void injectLanguages(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) { if(myManager.myConcatenationInjectors.isEmpty()) { return; } final PsiFile containingFile = ((InjectionRegistrarImpl) registrar).getHostPsiFile(); Project project = containingFile.getProject(); long modificationCount = PsiManager.getInstance(project).getModificationTracker().getModificationCount(); Pair<PsiElement, PsiElement[]> pair = computeAnchorAndOperands(context); PsiElement anchor = pair.first; PsiElement[] operands = pair.second; Integer noInjectionTimestamp = anchor.getUserData(NO_CONCAT_INJECTION_TIMESTAMP); InjectionResult result; ParameterizedCachedValue<InjectionResult, PsiElement> data = null; if(operands.length == 0 || noInjectionTimestamp != null && noInjectionTimestamp == modificationCount) { result = null; } else { data = anchor.getUserData(INJECTED_PSI_IN_CONCATENATION); result = data == null ? null : data.getValue(context); if(result == null || !result.isValid()) { result = doCompute(containingFile, project, anchor, operands); } } if(result != null) { ((InjectionRegistrarImpl) registrar).addToResults(result); if(data == null) { CachedValueProvider.Result<InjectionResult> cachedResult = CachedValueProvider.Result.create(result, PsiModificationTracker.MODIFICATION_COUNT, myManager); data = CachedValuesManager.getManager(project).createParameterizedCachedValue(context1 -> { PsiFile containingFile1 = context1.getContainingFile(); Project project1 = containingFile1.getProject(); Pair<PsiElement, PsiElement[]> pair1 = computeAnchorAndOperands(context1); InjectionResult result1 = pair1.second.length == 0 ? null : doCompute(containingFile1, project1, pair1.first, pair1.second); return result1 == null ? null : CachedValueProvider.Result.create(result1, PsiModificationTracker.MODIFICATION_COUNT, myManager); }, false); ((PsiParameterizedCachedValue<InjectionResult, PsiElement>) data).setValue(cachedResult); anchor.putUserData(INJECTED_PSI_IN_CONCATENATION, data); if(anchor.getUserData(NO_CONCAT_INJECTION_TIMESTAMP) != null) { anchor.putUserData(NO_CONCAT_INJECTION_TIMESTAMP, null); } } } else { // cache no-injection flag if(anchor.getUserData(INJECTED_PSI_IN_CONCATENATION) != null) { anchor.putUserData(INJECTED_PSI_IN_CONCATENATION, null); } anchor.putUserData(NO_CONCAT_INJECTION_TIMESTAMP, (int) modificationCount); } }