update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / psi / impl / PsiJavaParserFacadeImpl.java
blob93f7c2fa3b29a719f27b5962035368c052fb0d3b
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @author max
20 package com.intellij.psi.impl;
22 import com.intellij.ide.fileTemplates.FileTemplate;
23 import com.intellij.ide.fileTemplates.FileTemplateManager;
24 import com.intellij.ide.fileTemplates.JavaTemplateUtil;
25 import com.intellij.openapi.diagnostic.Logger;
26 import com.intellij.openapi.fileTypes.FileType;
27 import com.intellij.openapi.fileTypes.StdFileTypes;
28 import com.intellij.openapi.progress.ProcessCanceledException;
29 import com.intellij.openapi.roots.LanguageLevelProjectExtension;
30 import com.intellij.pom.java.LanguageLevel;
31 import com.intellij.psi.*;
32 import com.intellij.psi.impl.source.DummyHolderFactory;
33 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
34 import com.intellij.psi.impl.source.parsing.DeclarationParsing;
35 import com.intellij.psi.impl.source.parsing.ExpressionParsing;
36 import com.intellij.psi.impl.source.parsing.JavaParsingContext;
37 import com.intellij.psi.impl.source.parsing.Parsing;
38 import com.intellij.psi.impl.source.tree.CompositeElement;
39 import com.intellij.psi.impl.source.tree.FileElement;
40 import com.intellij.psi.impl.source.tree.JavaElementType;
41 import com.intellij.psi.impl.source.tree.TreeElement;
42 import com.intellij.psi.javadoc.PsiDocComment;
43 import com.intellij.psi.javadoc.PsiDocTag;
44 import com.intellij.psi.util.PsiUtil;
45 import com.intellij.util.IncorrectOperationException;
46 import com.intellij.util.containers.HashMap;
47 import org.jetbrains.annotations.NonNls;
48 import org.jetbrains.annotations.NotNull;
50 import java.util.Map;
51 import java.util.Properties;
53 public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJavaParserFacade {
54 private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiJavaParserFacadeImpl");
56 protected static final Map<String, PsiPrimitiveType> ourPrimitiveTypesMap = new HashMap<String, PsiPrimitiveType>();
57 protected PsiJavaFile myDummyJavaFile;
59 public PsiJavaParserFacadeImpl(PsiManagerEx manager) {
60 super(manager);
63 @NotNull
64 public PsiAnnotation createAnnotationFromText(@NotNull String annotationText, PsiElement context) throws IncorrectOperationException {
65 final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
66 CompositeElement annotationElement = getJavaParsingContext(holderElement).getDeclarationParsing().parseAnnotationFromText(myManager, annotationText, getLanguageLevel(context));
67 if (annotationElement == null || annotationElement.getElementType() != JavaElementType.ANNOTATION) {
68 throw new IncorrectOperationException("Incorrect annotation \"" + annotationText + "\".");
70 holderElement.rawAddChildren(annotationElement);
71 return (PsiAnnotation)SourceTreeToPsiMap.treeElementToPsi(annotationElement);
74 private LanguageLevel getLanguageLevel(final PsiElement context) {
75 if (context == null) {
76 return LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel();
78 return PsiUtil.getLanguageLevel(context);
81 @NotNull
82 public PsiDocTag createDocTagFromText(@NotNull String docTagText, PsiElement context) throws IncorrectOperationException {
83 StringBuilder buffer = new StringBuilder();
84 buffer.append("/**\n");
85 buffer.append(docTagText);
86 buffer.append("\n */");
87 PsiDocComment comment = createDocCommentFromText(buffer.toString(), context);
88 return comment.getTags()[0];
91 @NotNull
92 public PsiDocComment createDocCommentFromText(@NotNull String docCommentText, PsiElement context) throws IncorrectOperationException {
93 @NonNls StringBuilder buffer = new StringBuilder();
94 buffer.append(docCommentText);
95 buffer.append("void m();");
96 final PsiMethod method = createMethodFromText(buffer.toString(), null);
97 return method.getDocComment();
100 @NotNull
101 public PsiClass createClassFromText(@NotNull String body, PsiElement context) throws IncorrectOperationException {
102 @NonNls String fileText = "class _Dummy_ { " + body + " }";
103 PsiJavaFile aFile = createDummyJavaFile(fileText);
104 PsiClass[] classes = aFile.getClasses();
105 if (classes.length != 1) {
106 throw new IncorrectOperationException("Incorrect class \"" + body + "\".");
108 return classes[0];
111 @NotNull
112 public PsiField createFieldFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException {
113 final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
114 TreeElement decl = getJavaParsingContext(holderElement).getDeclarationParsing().parseDeclarationText(myManager, LanguageLevelProjectExtension
115 .getInstance(myManager.getProject()).getLanguageLevel(), text, DeclarationParsing.Context.CLASS_CONTEXT);
116 if (decl == null || decl.getElementType() != JavaElementType.FIELD) {
117 throw new IncorrectOperationException("Incorrect field \"" + text + "\".");
119 holderElement.rawAddChildren(decl);
120 return (PsiField)SourceTreeToPsiMap.treeElementToPsi(decl);
123 protected JavaParsingContext getJavaParsingContext (FileElement holderElement) {
124 return new JavaParsingContext(holderElement.getCharTable(), LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel());
127 private static JavaParsingContext getJavaParsingContext (FileElement holderElement, LanguageLevel languageLevel) {
128 return new JavaParsingContext(holderElement.getCharTable(), languageLevel);
131 @NotNull
132 public PsiMethod createMethodFromText(@NotNull String text, PsiElement context, LanguageLevel level) throws IncorrectOperationException {
133 final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
134 TreeElement decl = getJavaParsingContext(holderElement, level).getDeclarationParsing().parseDeclarationText(myManager, level, text,
135 DeclarationParsing.Context.CLASS_CONTEXT);
136 if (decl == null || decl.getElementType() != JavaElementType.METHOD) {
137 throw new IncorrectOperationException("Incorrect method \"" + text + "\".");
139 holderElement.rawAddChildren(decl);
140 return (PsiMethod)SourceTreeToPsiMap.treeElementToPsi(decl);
143 @NotNull
144 public final PsiMethod createMethodFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException {
145 return createMethodFromText(text, context, LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel());
148 @NotNull
149 public PsiParameter createParameterFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException {
150 final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
151 CompositeElement param = getJavaParsingContext(holderElement).getDeclarationParsing().parseParameterText(text);
152 if (param == null) {
153 throw new IncorrectOperationException("Incorrect parameter \"" + text + "\".");
155 holderElement.rawAddChildren(param);
156 return (PsiParameter)SourceTreeToPsiMap.treeElementToPsi(param);
159 @NotNull
160 public PsiType createTypeFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException {
161 return createTypeInner(text, context, false);
164 protected PsiType createTypeInner(final String text, final PsiElement context, boolean markAsCopy) throws IncorrectOperationException {
165 PsiPrimitiveType primitiveType = ourPrimitiveTypesMap.get(text);
166 if (primitiveType != null) return primitiveType;
167 final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
168 CompositeElement typeElement = Parsing.parseTypeText(myManager, text, 0, text.length(), holderElement.getCharTable());
169 if (typeElement == null) {
170 throw new IncorrectOperationException("Incorrect type \"" + text + "\"");
172 holderElement.rawAddChildren(typeElement);
173 if (markAsCopy) {
174 holderElement.acceptTree(new GeneratedMarkerVisitor());
176 PsiTypeElement psiTypeElement = (PsiTypeElement)SourceTreeToPsiMap.treeElementToPsi(typeElement);
177 if (psiTypeElement == null) {
178 throw new IncorrectOperationException("PSI is null for element "+typeElement);
180 return psiTypeElement.getType();
183 @NotNull
184 public PsiCodeBlock createCodeBlockFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException {
185 final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
186 CompositeElement treeElement = getJavaParsingContext(holderElement).getStatementParsing().parseCodeBlockText(myManager, text);
187 if (treeElement == null) {
188 throw new IncorrectOperationException("Incorrect code block \"" + text + "\".");
190 holderElement.rawAddChildren(treeElement);
191 return (PsiCodeBlock)SourceTreeToPsiMap.treeElementToPsi(treeElement);
194 @NotNull
195 public PsiStatement createStatementFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException {
196 final FileElement treeHolder = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
197 TreeElement treeElement = getJavaParsingContext(treeHolder).getStatementParsing().parseStatementText(text);
198 if (treeElement == null) {
199 throw new IncorrectOperationException("Incorrect statement \"" + text + "\".");
201 treeHolder.rawAddChildren(treeElement);
202 return (PsiStatement)SourceTreeToPsiMap.treeElementToPsi(treeElement);
205 @NotNull
206 public PsiExpression createExpressionFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException {
207 final FileElement treeHolder = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
208 final CompositeElement treeElement = ExpressionParsing.parseExpressionText(myManager, text, 0,
209 text.length(), treeHolder.getCharTable());
210 if (treeElement == null) {
211 throw new IncorrectOperationException("Incorrect expression \"" + text + "\".");
213 treeHolder.rawAddChildren(treeElement);
214 return (PsiExpression)SourceTreeToPsiMap.treeElementToPsi(treeElement);
217 protected PsiJavaFile createDummyJavaFile(String text) {
218 String ext = StdFileTypes.JAVA.getDefaultExtension();
219 @NonNls String fileName = "_Dummy_." + ext;
220 FileType type = StdFileTypes.JAVA;
222 return (PsiJavaFile)PsiFileFactory.getInstance(myManager.getProject()).createFileFromText(type, fileName, text, 0, text.length());
225 @NotNull
226 public PsiTypeParameter createTypeParameterFromText(@NotNull String text, PsiElement context)
227 throws IncorrectOperationException {
228 final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
229 TreeElement treeElement = getJavaParsingContext(holderElement).getDeclarationParsing().parseTypeParameterText(text);
230 if (treeElement == null) {
231 throw new IncorrectOperationException("Incorrect type parameter \"" + text + "\"");
233 holderElement.rawAddChildren(treeElement);
234 return (PsiTypeParameter)SourceTreeToPsiMap.treeElementToPsi(treeElement);
237 @NotNull
238 public PsiComment createCommentFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException {
239 PsiJavaFile aFile = createDummyJavaFile(text);
240 PsiElement[] children = aFile.getChildren();
241 for (PsiElement aChildren : children) {
242 if (aChildren instanceof PsiComment) {
243 if (!aChildren.getText().equals(text)) {
244 throw new IncorrectOperationException("Incorrect comment \"" + text + "\".");
246 PsiComment comment = (PsiComment)aChildren;
247 DummyHolderFactory.createHolder(myManager, (TreeElement)SourceTreeToPsiMap.psiElementToTree(comment), context);
248 return comment;
251 throw new IncorrectOperationException("Incorrect comment \"" + text + "\".");
254 @NotNull
255 public PsiEnumConstant createEnumConstantFromText(@NotNull String text, PsiElement context) throws IncorrectOperationException {
256 final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
257 TreeElement decl = getJavaParsingContext(holderElement).getDeclarationParsing().parseEnumConstantText(text);
258 if (decl == null || decl.getElementType() != JavaElementType.ENUM_CONSTANT) {
259 throw new IncorrectOperationException("Incorrect enum constant text \"" + text + "\".");
261 holderElement.rawAddChildren(decl);
262 return (PsiEnumConstant)SourceTreeToPsiMap.treeElementToPsi(decl);
265 @NotNull
266 public PsiCatchSection createCatchSection(@NotNull PsiClassType exceptionType,
267 @NotNull String exceptionName,
268 PsiElement context) throws IncorrectOperationException {
269 @NonNls StringBuilder buffer = new StringBuilder();
270 buffer.append("catch (");
271 buffer.append(exceptionType.getCanonicalText());
272 buffer.append(" ").append(exceptionName).append("){}");
273 String catchSectionText = buffer.toString();
274 final FileElement holderElement = DummyHolderFactory.createHolder(myManager, context).getTreeElement();
275 TreeElement catchSection = getJavaParsingContext(holderElement).getStatementParsing().parseCatchSectionText(catchSectionText);
276 LOG.assertTrue(catchSection != null && catchSection.getElementType() == JavaElementType.CATCH_SECTION);
277 holderElement.rawAddChildren(catchSection);
278 PsiCatchSection psiCatchSection = (PsiCatchSection)SourceTreeToPsiMap.treeElementToPsi(catchSection);
280 setupCatchBlock(exceptionName, context, psiCatchSection);
281 return (PsiCatchSection)myManager.getCodeStyleManager().reformat(psiCatchSection);
284 private void setupCatchBlock(String exceptionName, PsiElement context, PsiCatchSection psiCatchSection)
285 throws IncorrectOperationException {
286 FileTemplate catchBodyTemplate = FileTemplateManager.getInstance().getCodeTemplate(JavaTemplateUtil.TEMPLATE_CATCH_BODY);
287 LOG.assertTrue(catchBodyTemplate != null);
289 Properties props = new Properties();
290 props.setProperty(FileTemplate.ATTRIBUTE_EXCEPTION, exceptionName);
291 if (context != null && context.isPhysical()) {
292 PsiDirectory directory = context.getContainingFile().getContainingDirectory();
293 if (directory != null) {
294 JavaTemplateUtil.setPackageNameAttribute(props, directory);
297 PsiCodeBlock codeBlockFromText;
298 try {
299 String catchBody = catchBodyTemplate.getText(props);
300 codeBlockFromText = createCodeBlockFromText("{\n" + catchBody + "\n}", null);
302 catch (ProcessCanceledException ce) {
303 throw ce;
305 catch (Exception e) {
306 throw new IncorrectOperationException("Incorrect file template",e);
308 psiCatchSection.getCatchBlock().replace(codeBlockFromText);
311 public PsiType createPrimitiveType(@NotNull String text, @NotNull PsiAnnotation[] annotations) {
312 if (annotations.length == 0) {
313 return PsiElementFactoryImpl.getPrimitiveType(text);//todo
315 return new PsiPrimitiveType(text, annotations);