fix "IDEA-221944 Deadlock on opening second project" and support preloading for proje...
[idea/community.git] / platform / core-impl / src / com / intellij / psi / impl / PsiParserFacadeImpl.java
1 // Copyright 2000-2019 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.
2
3 package com.intellij.psi.impl;
4
5 import com.intellij.lang.ASTFactory;
6 import com.intellij.lang.Commenter;
7 import com.intellij.lang.Language;
8 import com.intellij.lang.LanguageCommenters;
9 import com.intellij.openapi.fileTypes.LanguageFileType;
10 import com.intellij.openapi.project.Project;
11 import com.intellij.psi.*;
12 import com.intellij.psi.impl.source.DummyHolderFactory;
13 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
14 import com.intellij.psi.impl.source.tree.FileElement;
15 import com.intellij.psi.impl.source.tree.LeafElement;
16 import com.intellij.psi.impl.source.tree.TreeElement;
17 import com.intellij.util.IncorrectOperationException;
18 import org.jetbrains.annotations.NonNls;
19 import org.jetbrains.annotations.NotNull;
20
21 /**
22  * @author yole
23  */
24 public final class PsiParserFacadeImpl implements PsiParserFacade {
25   private final PsiManagerEx myManager;
26
27   public PsiParserFacadeImpl(@NotNull Project project) {
28     myManager = PsiManagerEx.getInstanceEx(project);
29   }
30
31   @Override
32   @NotNull
33   public PsiElement createWhiteSpaceFromText(@NotNull @NonNls String text) throws IncorrectOperationException {
34     final FileElement holderElement = DummyHolderFactory.createHolder(myManager, null).getTreeElement();
35     final LeafElement newElement = ASTFactory.leaf(TokenType.WHITE_SPACE, holderElement.getCharTable().intern(text));
36     holderElement.rawAddChildren(newElement);
37     GeneratedMarkerVisitor.markGenerated(newElement.getPsi());
38     return newElement.getPsi();
39   }
40
41   @Override
42   @NotNull
43   public PsiComment createLineCommentFromText(@NotNull final LanguageFileType fileType,
44                                               @NotNull final String text) throws IncorrectOperationException {
45     Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(fileType.getLanguage());
46     assert commenter != null;
47     String prefix = commenter.getLineCommentPrefix();
48     if (prefix == null) {
49       throw new IncorrectOperationException("No line comment prefix defined for language " + fileType.getLanguage().getID());
50     }
51
52     PsiFile aFile = createDummyFile(prefix + text, fileType);
53     return findPsiCommentChild(aFile);
54   }
55
56   @NotNull
57   @Override
58   public PsiComment createBlockCommentFromText(@NotNull Language language, @NotNull String text) throws IncorrectOperationException {
59     Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(language);
60     assert commenter != null : language;
61     final String blockCommentPrefix = commenter.getBlockCommentPrefix();
62     final String blockCommentSuffix = commenter.getBlockCommentSuffix();
63
64     PsiFile aFile = PsiFileFactory.getInstance(myManager.getProject()).createFileFromText("_Dummy_", language,
65                                                                                           (blockCommentPrefix + text + blockCommentSuffix));
66     return findPsiCommentChild(aFile);
67   }
68
69   @Override
70   @NotNull
71   public PsiComment createLineOrBlockCommentFromText(@NotNull Language lang, @NotNull String text)
72     throws IncorrectOperationException {
73     Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(lang);
74     assert commenter != null:lang;
75     String prefix = commenter.getLineCommentPrefix();
76     final String blockCommentPrefix = commenter.getBlockCommentPrefix();
77     final String blockCommentSuffix = commenter.getBlockCommentSuffix();
78     assert prefix != null || (blockCommentPrefix != null && blockCommentSuffix != null);
79
80     PsiFile aFile = PsiFileFactory.getInstance(myManager.getProject()).createFileFromText("_Dummy_", lang, prefix != null ? (prefix + text) : (blockCommentPrefix + text + blockCommentSuffix));
81     return findPsiCommentChild(aFile);
82   }
83
84   private PsiComment findPsiCommentChild(PsiFile aFile) {
85     PsiElement[] children = aFile.getChildren();
86     for (PsiElement aChildren : children) {
87       if (aChildren instanceof PsiComment) {
88         PsiComment comment = (PsiComment)aChildren;
89         DummyHolderFactory.createHolder(myManager, (TreeElement)SourceTreeToPsiMap.psiElementToTree(comment), null);
90         return comment;
91       }
92     }
93     throw new IncorrectOperationException("Incorrect comment \"" + aFile.getText() + "\".");
94   }
95
96   private PsiFile createDummyFile(String text, final LanguageFileType fileType) {
97     String ext = fileType.getDefaultExtension();
98     @NonNls String fileName = "_Dummy_." + ext;
99
100     return PsiFileFactory.getInstance(myManager.getProject()).createFileFromText(fileType, fileName, text, 0, text.length());
101   }
102 }