cancel reparsing if psi is reloaded anyway (e.g. FilePropertyPusher reloads psi); don't reparse for the first language substitution (everything seems to work in this case) (IDEA-CR-11333)

This commit is contained in:
Sergey Simonchik
2016-06-09 18:51:34 +03:00
parent 4fcf968d69
commit bfc60ee494
2 changed files with 16 additions and 27 deletions
@@ -35,8 +35,7 @@ public final class LanguageSubstitutors extends LanguageExtension<LanguageSubsti
public static final LanguageSubstitutors INSTANCE = new LanguageSubstitutors();
private static final Logger LOG = Logger.getInstance(LanguageSubstitutors.class);
private static final Key<Language> SUBSTITUTED_LANG_KEY = Key.create("SUBSTITUTED_LANG_KEY");
private boolean myReparsingInProgress;
private static final Key<Boolean> REPARSING_SCHEDULED = Key.create("REPARSING_SCHEDULED");
private LanguageSubstitutors() {
super("com.intellij.lang.substitutor");
@@ -55,9 +54,9 @@ public final class LanguageSubstitutors extends LanguageExtension<LanguageSubsti
}
private void processLanguageSubstitution(@NotNull final VirtualFile file,
@NotNull Language originalLang,
@NotNull final Language substitutedLang) {
private static void processLanguageSubstitution(@NotNull final VirtualFile file,
@NotNull Language originalLang,
@NotNull final Language substitutedLang) {
if (file instanceof VirtualFileWindow) {
// Injected files are created with substituted language, no need to reparse:
// com.intellij.psi.impl.source.tree.injected.MultiHostRegistrarImpl#doneInjecting
@@ -65,41 +64,30 @@ public final class LanguageSubstitutors extends LanguageExtension<LanguageSubsti
}
Language prevSubstitutedLang = SUBSTITUTED_LANG_KEY.get(file);
final Language prevLang = ObjectUtils.notNull(prevSubstitutedLang, originalLang);
if (!haveCommonAncestorLanguage(substitutedLang, prevLang)) {
if (!prevLang.is(substitutedLang)) {
if (file.replace(SUBSTITUTED_LANG_KEY, prevSubstitutedLang, substitutedLang)) {
if (ApplicationManager.getApplication().isDispatchThread() && myReparsingInProgress) {
return; // avoid recursive reparsing
if (prevSubstitutedLang == null) {
return; // no need to reparse for the first language substitution
}
if (ApplicationManager.getApplication().isUnitTestMode()) {
return;
}
file.putUserData(REPARSING_SCHEDULED, true);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
LOG.info("Reparsing " + file.getPath() + " because of language substitution " +
prevLang.getID() + "->" + substitutedLang.getID());
myReparsingInProgress = true;
FileContentUtilCore.reparseFiles(file);
myReparsingInProgress = false;
if (file.replace(REPARSING_SCHEDULED, true, null)) {
LOG.info("Reparsing " + file.getPath() + " because of language substitution " +
prevLang.getID() + "->" + substitutedLang.getID());
FileContentUtilCore.reparseFiles(file);
}
}
}, ModalityState.defaultModalityState());
}
}
}
private static boolean haveCommonAncestorLanguage(@NotNull Language lang1, @NotNull Language lang2) {
Language rootLang1 = findRootLanguage(lang1);
Language rootLang2 = findRootLanguage(lang2);
return rootLang1.is(rootLang2);
}
@NotNull
private static Language findRootLanguage(@NotNull Language lang) {
Language parent = lang.getBaseLanguage();
while (parent != null) {
lang = parent;
parent = lang.getBaseLanguage();
}
return lang;
public static void cancelReparsing(@NotNull VirtualFile file) {
REPARSING_SCHEDULED.set(file, null);
}
}
@@ -146,6 +146,7 @@ public class FileManagerImpl implements FileManager {
}
public void forceReload(@NotNull VirtualFile vFile) {
LanguageSubstitutors.cancelReparsing(vFile);
if (findCachedViewProvider(vFile) == null) {
return;
}