| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.psi.impl; |
| |
| import com.intellij.lang.*; |
| import com.intellij.lang.java.lexer.JavaLexer; |
| import com.intellij.lang.java.parser.JavaParser; |
| import com.intellij.lang.java.parser.JavaParserUtil; |
| import com.intellij.lexer.Lexer; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.pom.java.LanguageLevel; |
| import com.intellij.psi.*; |
| import com.intellij.psi.codeStyle.CodeStyleManager; |
| import com.intellij.psi.codeStyle.JavaCodeStyleManager; |
| import com.intellij.psi.codeStyle.JavaCodeStyleSettingsFacade; |
| import com.intellij.psi.impl.light.*; |
| import com.intellij.psi.impl.source.*; |
| import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; |
| import com.intellij.psi.impl.source.tree.FileElement; |
| import com.intellij.psi.impl.source.tree.TreeElement; |
| import com.intellij.psi.javadoc.PsiDocTag; |
| import com.intellij.psi.search.GlobalSearchScope; |
| import com.intellij.psi.tree.IElementType; |
| import com.intellij.psi.util.PsiUtil; |
| import com.intellij.util.IncorrectOperationException; |
| import com.intellij.util.containers.ConcurrentHashMap; |
| import com.intellij.util.containers.HashMap; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.Map; |
| |
| public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements PsiElementFactory { |
| private PsiClass myArrayClass; |
| private PsiClass myArrayClass15; |
| private final ConcurrentHashMap<GlobalSearchScope, PsiClassType> myCachedObjectType = new ConcurrentHashMap<GlobalSearchScope, PsiClassType>(); |
| |
| public PsiElementFactoryImpl(final PsiManagerEx manager) { |
| super(manager); |
| manager.registerRunnableToRunOnChange(new Runnable() { |
| @Override |
| public void run() { |
| myCachedObjectType.clear(); |
| } |
| }); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClass getArrayClass(@NotNull final LanguageLevel languageLevel) { |
| if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) { |
| if (myArrayClass == null) { |
| @NonNls final String body = "public class __Array__{\n public final int length;\n public Object clone() {}\n}"; |
| myArrayClass = ((PsiExtensibleClass)createClassFromText(body, null)).getOwnInnerClasses().get(0); |
| } |
| return myArrayClass; |
| } |
| else { |
| if (myArrayClass15 == null) { |
| @NonNls final String body = "public class __Array__<T>{\n public final int length;\n public T[] clone() {}\n}"; |
| myArrayClass15 = ((PsiExtensibleClass)createClassFromText(body, null)).getOwnInnerClasses().get(0); |
| } |
| return myArrayClass15; |
| } |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType getArrayClassType(@NotNull final PsiType componentType, @NotNull final LanguageLevel languageLevel) { |
| final PsiClass arrayClass = getArrayClass(languageLevel); |
| final PsiTypeParameter[] typeParameters = arrayClass.getTypeParameters(); |
| |
| PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; |
| if (typeParameters.length == 1) { |
| substitutor = substitutor.put(typeParameters[0], componentType); |
| } |
| |
| return createType(arrayClass, substitutor); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor) { |
| return new PsiImmediateClassType(resolve, substitutor); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel) { |
| return new PsiImmediateClassType(resolve, substitutor, languageLevel); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType createType(@NotNull PsiClass resolve, |
| @NotNull PsiSubstitutor substitutor, |
| @Nullable LanguageLevel languageLevel, |
| @NotNull PsiAnnotation[] annotations) { |
| return new PsiImmediateClassType(resolve, substitutor, languageLevel, annotations); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClass createClass(@NotNull final String name) throws IncorrectOperationException { |
| return createClassInner("class", name); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClass createInterface(@NotNull final String name) throws IncorrectOperationException { |
| return createClassInner("interface", name); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClass createEnum(@NotNull final String name) throws IncorrectOperationException { |
| return createClassInner("enum", name); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClass createAnnotationType(@NotNull @NonNls String name) throws IncorrectOperationException { |
| return createClassInner("@interface", name); |
| } |
| |
| private PsiClass createClassInner(@NonNls final String type, @NonNls String name) { |
| PsiUtil.checkIsIdentifier(myManager, name); |
| final PsiJavaFile aFile = createDummyJavaFile("public " + type + " " + name + " { }"); |
| final PsiClass[] classes = aFile.getClasses(); |
| if (classes.length != 1) { |
| throw new IncorrectOperationException("Incorrect " + type + " name \"" + name + "\"."); |
| } |
| return classes[0]; |
| } |
| |
| @NotNull |
| @Override |
| public PsiTypeElement createTypeElement(@NotNull final PsiType psiType) { |
| final LightTypeElement element = new LightTypeElement(myManager, psiType); |
| CodeEditUtil.setNodeGenerated(element.getNode(), true); |
| return element; |
| } |
| |
| @NotNull |
| @Override |
| public PsiJavaCodeReferenceElement createReferenceElementByType(@NotNull final PsiClassType type) { |
| if (type instanceof PsiClassReferenceType) { |
| return ((PsiClassReferenceType)type).getReference(); |
| } |
| |
| final PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics(); |
| final PsiClass refClass = resolveResult.getElement(); |
| assert refClass != null : type; |
| return new LightClassReference(myManager, type.getCanonicalText(true), refClass, resolveResult.getSubstitutor()); |
| } |
| |
| @NotNull |
| @Override |
| public PsiTypeParameterList createTypeParameterList() { |
| final PsiTypeParameterList parameterList = createMethodFromText("void foo()", null).getTypeParameterList(); |
| assert parameterList != null; |
| return parameterList; |
| } |
| |
| @NotNull |
| @Override |
| public PsiTypeParameter createTypeParameter(String name, PsiClassType[] superTypes) { |
| @NonNls StringBuilder builder = new StringBuilder(); |
| builder.append("public <").append(name); |
| if (superTypes.length > 1 || |
| superTypes.length == 1 && !superTypes[0].equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { |
| builder.append(" extends "); |
| for (PsiClassType type : superTypes) { |
| if (type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) continue; |
| builder.append(type.getCanonicalText(true)).append('&'); |
| } |
| |
| builder.delete(builder.length() - 1, builder.length()); |
| } |
| builder.append("> void foo(){}"); |
| try { |
| return createMethodFromText(builder.toString(), null).getTypeParameters()[0]; |
| } |
| catch (RuntimeException e) { |
| throw new IncorrectOperationException("type parameter text: " + builder.toString()); |
| } |
| } |
| |
| @NotNull |
| @Override |
| public PsiField createField(@NotNull final String name, @NotNull final PsiType type) throws IncorrectOperationException { |
| PsiUtil.checkIsIdentifier(myManager, name); |
| if (PsiType.NULL.equals(type)) { |
| throw new IncorrectOperationException("Cannot create field with type \"null\"."); |
| } |
| |
| @NonNls final String text = "class _Dummy_ { private " + type.getCanonicalText(true) + " " + name + "; }"; |
| final PsiJavaFile aFile = createDummyJavaFile(text); |
| final PsiClass[] classes = aFile.getClasses(); |
| if (classes.length < 1) { |
| throw new IncorrectOperationException("Class was not created " + text); |
| } |
| final PsiClass psiClass = classes[0]; |
| final PsiField[] fields = psiClass.getFields(); |
| if (fields.length < 1) { |
| throw new IncorrectOperationException("Field was not created " + text); |
| } |
| PsiField field = fields[0]; |
| field = (PsiField)JavaCodeStyleManager.getInstance(myManager.getProject()).shortenClassReferences(field); |
| return (PsiField)CodeStyleManager.getInstance(myManager.getProject()).reformat(field); |
| } |
| |
| @NotNull |
| @Override |
| public PsiMethod createMethod(@NotNull final String name, final PsiType returnType) throws IncorrectOperationException { |
| PsiUtil.checkIsIdentifier(myManager, name); |
| if (PsiType.NULL.equals(returnType)) { |
| throw new IncorrectOperationException("Cannot create method with type \"null\"."); |
| } |
| |
| final String canonicalText = returnType.getCanonicalText(true); |
| final PsiJavaFile aFile = createDummyJavaFile("class _Dummy_ { public " + canonicalText + " " + name + "() {} }"); |
| final PsiClass[] classes = aFile.getClasses(); |
| if (classes.length < 1) { |
| throw new IncorrectOperationException("Class was not created. Method name: " + name + "; return type: " + canonicalText); |
| } |
| final PsiMethod[] methods = classes[0].getMethods(); |
| if (methods.length < 1) { |
| throw new IncorrectOperationException("Method was not created. Method name: " + name + "; return type: " + canonicalText); |
| } |
| PsiMethod method = methods[0]; |
| method = (PsiMethod)JavaCodeStyleManager.getInstance(myManager.getProject()).shortenClassReferences(method); |
| return (PsiMethod)CodeStyleManager.getInstance(myManager.getProject()).reformat(method); |
| } |
| |
| @NotNull |
| @Override |
| public PsiMethod createConstructor() { |
| return createConstructor("_Dummy_"); |
| } |
| |
| @NotNull |
| @Override |
| public PsiMethod createConstructor(@NotNull @NonNls final String name) { |
| final PsiJavaFile aFile = createDummyJavaFile("class " + name + " { public " + name + "() {} }"); |
| final PsiMethod method = aFile.getClasses()[0].getMethods()[0]; |
| return (PsiMethod)CodeStyleManager.getInstance(myManager.getProject()).reformat(method); |
| } |
| |
| @Override |
| public PsiMethod createConstructor(@NotNull @NonNls String name, PsiElement context) { |
| return createMethodFromText(name + "() {}", context); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassInitializer createClassInitializer() throws IncorrectOperationException { |
| final PsiJavaFile aFile = createDummyJavaFile("class _Dummy_ { {} }"); |
| final PsiClassInitializer classInitializer = aFile.getClasses()[0].getInitializers()[0]; |
| return (PsiClassInitializer)CodeStyleManager.getInstance(myManager.getProject()).reformat(classInitializer); |
| } |
| |
| @NotNull |
| @Override |
| public PsiParameter createParameter(@NotNull final String name, @NotNull final PsiType type) throws IncorrectOperationException { |
| PsiUtil.checkIsIdentifier(myManager, name); |
| if (PsiType.NULL.equals(type)) { |
| throw new IncorrectOperationException("Cannot create parameter with type \"null\"."); |
| } |
| |
| final String text = type.getCanonicalText(true) + " " + name; |
| PsiParameter parameter = createParameterFromText(text, null); |
| final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(myManager.getProject()); |
| PsiUtil.setModifierProperty(parameter, PsiModifier.FINAL, |
| JavaCodeStyleSettingsFacade.getInstance(myManager.getProject()).isGenerateFinalParameters()); |
| GeneratedMarkerVisitor.markGenerated(parameter); |
| parameter = (PsiParameter)JavaCodeStyleManager.getInstance(myManager.getProject()).shortenClassReferences(parameter); |
| return (PsiParameter)codeStyleManager.reformat(parameter); |
| } |
| |
| @Override |
| public PsiParameter createParameter(@NotNull @NonNls String name, PsiType type, PsiElement context) throws IncorrectOperationException { |
| final PsiMethod psiMethod = createMethodFromText("void f(" + type.getCanonicalText(true) + " " + name + ") {}", context); |
| final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); |
| return parameters[0]; |
| } |
| |
| @NotNull |
| @Override |
| public PsiCodeBlock createCodeBlock() { |
| final PsiCodeBlock block = createCodeBlockFromText("{}", null); |
| return (PsiCodeBlock)CodeStyleManager.getInstance(myManager.getProject()).reformat(block); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType createType(@NotNull final PsiClass aClass) { |
| return new PsiImmediateClassType(aClass, aClass instanceof PsiTypeParameter ? PsiSubstitutor.EMPTY : createRawSubstitutor(aClass)); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType createType(@NotNull final PsiJavaCodeReferenceElement classReference) { |
| return new PsiClassReferenceType(classReference, null); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType createType(@NotNull final PsiClass aClass, final PsiType parameter) { |
| final PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); |
| assert typeParameters.length == 1 : aClass; |
| |
| return createType(aClass, PsiSubstitutor.EMPTY.put(typeParameters[0], parameter)); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType createType(@NotNull final PsiClass aClass, final PsiType... parameters) { |
| return createType(aClass, PsiSubstitutor.EMPTY.putAll(aClass, parameters)); |
| } |
| |
| @NotNull |
| @Override |
| public PsiSubstitutor createRawSubstitutor(@NotNull final PsiTypeParameterListOwner owner) { |
| Map<PsiTypeParameter, PsiType> substitutorMap = null; |
| for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(owner)) { |
| if (substitutorMap == null) substitutorMap = new HashMap<PsiTypeParameter, PsiType>(); |
| substitutorMap.put(parameter, null); |
| } |
| return PsiSubstitutorImpl.createSubstitutor(substitutorMap); |
| } |
| |
| @NotNull |
| @Override |
| public PsiSubstitutor createRawSubstitutor(@NotNull final PsiSubstitutor baseSubstitutor, @NotNull final PsiTypeParameter[] typeParameters) { |
| Map<PsiTypeParameter, PsiType> substitutorMap = null; |
| for (PsiTypeParameter parameter : typeParameters) { |
| if (substitutorMap == null) substitutorMap = new HashMap<PsiTypeParameter, PsiType>(); |
| substitutorMap.put(parameter, null); |
| } |
| return PsiSubstitutorImpl.createSubstitutor(substitutorMap).putAll(baseSubstitutor); |
| } |
| |
| @NotNull |
| @Override |
| public PsiElement createDummyHolder(@NotNull final String text, @NotNull final IElementType type, @Nullable final PsiElement context) { |
| final DummyHolder result = DummyHolderFactory.createHolder(myManager, context); |
| final FileElement holder = result.getTreeElement(); |
| final Language language = type.getLanguage(); |
| final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(language); |
| assert parserDefinition != null : "No parser definition for language " + language; |
| final Project project = myManager.getProject(); |
| final Lexer lexer = parserDefinition.createLexer(project); |
| final PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, holder, lexer, language, text); |
| final ASTNode node = parserDefinition.createParser(project).parse(type, builder); |
| holder.rawAddChildren((TreeElement)node); |
| final PsiElement psi = node.getPsi(); |
| assert psi != null : text; |
| return psi; |
| } |
| |
| @NotNull |
| @Override |
| public PsiSubstitutor createSubstitutor(@NotNull final Map<PsiTypeParameter, PsiType> map) { |
| return PsiSubstitutorImpl.createSubstitutor(map); |
| } |
| |
| @Nullable |
| @Override |
| public PsiPrimitiveType createPrimitiveType(@NotNull final String text) { |
| return PsiJavaParserFacadeImpl.getPrimitiveType(text); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType createTypeByFQClassName(@NotNull final String qName) { |
| return createTypeByFQClassName(qName, GlobalSearchScope.allScope(myManager.getProject())); |
| } |
| |
| @NotNull |
| @Override |
| public PsiClassType createTypeByFQClassName(@NotNull final String qName, @NotNull final GlobalSearchScope resolveScope) { |
| if (CommonClassNames.JAVA_LANG_OBJECT.equals(qName)) { |
| PsiClassType cachedObjectType = myCachedObjectType.get(resolveScope); |
| if (cachedObjectType != null) { |
| return cachedObjectType; |
| } |
| PsiClass aClass = JavaPsiFacade.getInstance(myManager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, resolveScope); |
| if (aClass != null) { |
| cachedObjectType = new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY); |
| cachedObjectType = myCachedObjectType.cacheOrGet(resolveScope, cachedObjectType); |
| return cachedObjectType; |
| } |
| } |
| return new PsiClassReferenceType(createReferenceElementByFQClassName(qName, resolveScope), null); |
| } |
| |
| @NotNull |
| @Override |
| public PsiJavaCodeReferenceElement createClassReferenceElement(@NotNull final PsiClass aClass) { |
| final String text; |
| if (aClass instanceof PsiAnonymousClass) { |
| text = ((PsiAnonymousClass)aClass).getBaseClassType().getPresentableText(); |
| } |
| else { |
| text = aClass.getName(); |
| } |
| return new LightClassReference(myManager, text, aClass); |
| } |
| |
| @NotNull |
| @Override |
| public PsiJavaCodeReferenceElement createReferenceElementByFQClassName(@NotNull final String qName, |
| @NotNull final GlobalSearchScope resolveScope) { |
| final String shortName = PsiNameHelper.getShortClassName(qName); |
| return new LightClassReference(myManager, shortName, qName, resolveScope); |
| } |
| |
| @NotNull |
| @Override |
| public PsiJavaCodeReferenceElement createFQClassNameReferenceElement(@NotNull final String qName, |
| @NotNull final GlobalSearchScope resolveScope) { |
| return new LightClassReference(myManager, qName, qName, resolveScope); |
| } |
| |
| @NotNull |
| @Override |
| public PsiJavaCodeReferenceElement createPackageReferenceElement(@NotNull final PsiPackage aPackage) throws IncorrectOperationException { |
| if (aPackage.getQualifiedName().isEmpty()) { |
| throw new IncorrectOperationException("Cannot create reference to default package."); |
| } |
| return new LightPackageReference(myManager, aPackage); |
| } |
| |
| @NotNull |
| @Override |
| public PsiPackageStatement createPackageStatement(@NotNull final String name) throws IncorrectOperationException { |
| final PsiJavaFile aFile = createDummyJavaFile("package " + name + ";"); |
| final PsiPackageStatement stmt = aFile.getPackageStatement(); |
| if (stmt == null) { |
| throw new IncorrectOperationException("Incorrect package name: " + name); |
| } |
| return stmt; |
| } |
| |
| @NotNull |
| @Override |
| public PsiImportStaticStatement createImportStaticStatement(@NotNull final PsiClass aClass, |
| @NotNull final String memberName) throws IncorrectOperationException { |
| if (aClass instanceof PsiAnonymousClass) { |
| throw new IncorrectOperationException("Cannot create import statement for anonymous class."); |
| } |
| else if (aClass.getParent() instanceof PsiDeclarationStatement) { |
| throw new IncorrectOperationException("Cannot create import statement for local class."); |
| } |
| |
| final PsiJavaFile aFile = createDummyJavaFile("import static " + aClass.getQualifiedName() + "." + memberName + ";"); |
| final PsiImportStatementBase statement = extractImport(aFile, true); |
| return (PsiImportStaticStatement)CodeStyleManager.getInstance(myManager.getProject()).reformat(statement); |
| } |
| |
| @NotNull |
| @Override |
| public PsiParameterList createParameterList(@NotNull final String[] names, @NotNull final PsiType[] types) throws IncorrectOperationException { |
| @NonNls StringBuilder builder = new StringBuilder(); |
| builder.append("void method("); |
| for (int i = 0; i < names.length; i++) { |
| if (i > 0) builder.append(", "); |
| builder.append(types[i].getCanonicalText(true)).append(' ').append(names[i]); |
| } |
| builder.append(");"); |
| return createMethodFromText(builder.toString(), null).getParameterList(); |
| } |
| |
| @NotNull |
| @Override |
| public PsiReferenceList createReferenceList(@NotNull final PsiJavaCodeReferenceElement[] references) throws IncorrectOperationException { |
| @NonNls final StringBuilder builder = new StringBuilder(); |
| builder.append("void method()"); |
| if (references.length > 0){ |
| builder.append(" throws "); |
| for (int i = 0; i < references.length; i++) { |
| if (i > 0) builder.append(", "); |
| builder.append(references[i].getCanonicalText()); |
| } |
| } |
| builder.append(';'); |
| return createMethodFromText(builder.toString(), null).getThrowsList(); |
| } |
| |
| @NotNull |
| @Override |
| public PsiJavaCodeReferenceElement createPackageReferenceElement(@NotNull final String packageName) throws IncorrectOperationException { |
| if (packageName.isEmpty()) { |
| throw new IncorrectOperationException("Cannot create reference to default package."); |
| } |
| return new LightPackageReference(myManager, packageName); |
| } |
| |
| @NotNull |
| @Override |
| public PsiReferenceExpression createReferenceExpression(@NotNull final PsiClass aClass) throws IncorrectOperationException { |
| final String text; |
| if (aClass instanceof PsiAnonymousClass) { |
| text = ((PsiAnonymousClass)aClass).getBaseClassType().getPresentableText(); |
| } |
| else { |
| text = aClass.getName(); |
| } |
| return new LightClassReferenceExpression(myManager, text, aClass); |
| } |
| |
| @NotNull |
| @Override |
| public PsiReferenceExpression createReferenceExpression(@NotNull final PsiPackage aPackage) throws IncorrectOperationException { |
| if (aPackage.getQualifiedName().isEmpty()) { |
| throw new IncorrectOperationException("Cannot create reference to default package."); |
| } |
| return new LightPackageReferenceExpression(myManager, aPackage); |
| } |
| |
| @NotNull |
| @Override |
| public PsiIdentifier createIdentifier(@NotNull final String text) throws IncorrectOperationException { |
| PsiUtil.checkIsIdentifier(myManager, text); |
| return new LightIdentifier(myManager, text); |
| } |
| |
| @NotNull |
| @Override |
| public PsiKeyword createKeyword(@NotNull final String text) throws IncorrectOperationException { |
| if (!PsiNameHelper.getInstance(myManager.getProject()).isKeyword(text)) { |
| throw new IncorrectOperationException("\"" + text + "\" is not a keyword."); |
| } |
| return new LightKeyword(myManager, text); |
| } |
| |
| @NotNull |
| @Override |
| public PsiKeyword createKeyword(@NotNull @NonNls String keyword, PsiElement context) throws IncorrectOperationException { |
| if (!JavaLexer.isKeyword(keyword, PsiUtil.getLanguageLevel(context))) { |
| throw new IncorrectOperationException("\"" + keyword + "\" is not a keyword."); |
| } |
| return new LightKeyword(myManager, keyword); |
| } |
| |
| @NotNull |
| @Override |
| public PsiImportStatement createImportStatement(@NotNull final PsiClass aClass) throws IncorrectOperationException { |
| if (aClass instanceof PsiAnonymousClass) { |
| throw new IncorrectOperationException("Cannot create import statement for anonymous class."); |
| } |
| else if (aClass.getParent() instanceof PsiDeclarationStatement) { |
| throw new IncorrectOperationException("Cannot create import statement for local class."); |
| } |
| |
| final PsiJavaFile aFile = createDummyJavaFile("import " + aClass.getQualifiedName() + ";"); |
| final PsiImportStatementBase statement = extractImport(aFile, false); |
| return (PsiImportStatement)CodeStyleManager.getInstance(myManager.getProject()).reformat(statement); |
| } |
| |
| @NotNull |
| @Override |
| public PsiImportStatement createImportStatementOnDemand(@NotNull final String packageName) throws IncorrectOperationException { |
| if (packageName.isEmpty()) { |
| throw new IncorrectOperationException("Cannot create import statement for default package."); |
| } |
| if (!PsiNameHelper.getInstance(myManager.getProject()).isQualifiedName(packageName)) { |
| throw new IncorrectOperationException("Incorrect package name: \"" + packageName + "\"."); |
| } |
| |
| final PsiJavaFile aFile = createDummyJavaFile("import " + packageName + ".*;"); |
| final PsiImportStatementBase statement = extractImport(aFile, false); |
| return (PsiImportStatement)CodeStyleManager.getInstance(myManager.getProject()).reformat(statement); |
| } |
| |
| @NotNull |
| @Override |
| public PsiDeclarationStatement createVariableDeclarationStatement(@NotNull String name, |
| @NotNull PsiType type, |
| @Nullable PsiExpression initializer) throws IncorrectOperationException { |
| if (!isIdentifier(name)) { |
| throw new IncorrectOperationException("\"" + name + "\" is not an identifier."); |
| } |
| if (PsiType.NULL.equals(type)) { |
| throw new IncorrectOperationException("Cannot create variable with type \"null\"."); |
| } |
| |
| String text = "X " + name + (initializer != null ? " = x" : "") + ";"; |
| PsiDeclarationStatement statement = (PsiDeclarationStatement)createStatementFromText(text, null); |
| |
| PsiVariable variable = (PsiVariable)statement.getDeclaredElements()[0]; |
| replace(variable.getTypeElement(), createTypeElement(type), text); |
| |
| boolean generateFinalLocals = JavaCodeStyleSettingsFacade.getInstance(myManager.getProject()).isGenerateFinalLocals(); |
| PsiUtil.setModifierProperty(variable, PsiModifier.FINAL, generateFinalLocals); |
| |
| if (initializer != null) { |
| replace(variable.getInitializer(), initializer, text); |
| } |
| |
| GeneratedMarkerVisitor.markGenerated(statement); |
| return statement; |
| } |
| |
| private static void replace(@Nullable PsiElement original, @NotNull PsiElement replacement, @NotNull String message) { |
| assert original != null : message; |
| original.replace(replacement); |
| } |
| |
| @NotNull |
| @Override |
| public PsiDocTag createParamTag(@NotNull final String parameterName, @NonNls final String description) throws IncorrectOperationException { |
| @NonNls final StringBuilder builder = new StringBuilder(); |
| builder.append(" * @param "); |
| builder.append(parameterName); |
| builder.append(" "); |
| final String[] strings = description.split("\\n"); |
| for (int i = 0; i < strings.length; i++) { |
| if (i > 0) builder.append("\n * "); |
| builder.append(strings[i]); |
| } |
| return createDocTagFromText(builder.toString()); |
| } |
| |
| @NotNull |
| @Override |
| public PsiAnnotation createAnnotationFromText(@NotNull final String annotationText, @Nullable final PsiElement context) throws IncorrectOperationException { |
| final PsiAnnotation psiAnnotation = super.createAnnotationFromText(annotationText, context); |
| GeneratedMarkerVisitor.markGenerated(psiAnnotation); |
| return psiAnnotation; |
| } |
| |
| @NotNull |
| @Override |
| public PsiCodeBlock createCodeBlockFromText(@NotNull final String text, @Nullable final PsiElement context) throws IncorrectOperationException { |
| final PsiCodeBlock psiCodeBlock = super.createCodeBlockFromText(text, context); |
| GeneratedMarkerVisitor.markGenerated(psiCodeBlock); |
| return psiCodeBlock; |
| } |
| |
| @NotNull |
| @Override |
| public PsiEnumConstant createEnumConstantFromText(@NotNull final String text, @Nullable final PsiElement context) throws IncorrectOperationException { |
| final PsiEnumConstant enumConstant = super.createEnumConstantFromText(text, context); |
| GeneratedMarkerVisitor.markGenerated(enumConstant); |
| return enumConstant; |
| } |
| |
| @NotNull |
| @Override |
| public PsiExpression createExpressionFromText(@NotNull final String text, @Nullable final PsiElement context) throws IncorrectOperationException { |
| final PsiExpression expression = super.createExpressionFromText(text, context); |
| GeneratedMarkerVisitor.markGenerated(expression); |
| return expression; |
| } |
| |
| @NotNull |
| @Override |
| public PsiField createFieldFromText(@NotNull final String text, @Nullable final PsiElement context) throws IncorrectOperationException { |
| final PsiField psiField = super.createFieldFromText(text, context); |
| GeneratedMarkerVisitor.markGenerated(psiField); |
| return psiField; |
| } |
| |
| @NotNull |
| @Override |
| public PsiParameter createParameterFromText(@NotNull final String text, @Nullable final PsiElement context) throws IncorrectOperationException { |
| final PsiParameter parameter = super.createParameterFromText(text, context); |
| GeneratedMarkerVisitor.markGenerated(parameter); |
| return parameter; |
| } |
| |
| @NotNull |
| @Override |
| public PsiStatement createStatementFromText(@NotNull final String text, @Nullable final PsiElement context) throws IncorrectOperationException { |
| final PsiStatement statement = super.createStatementFromText(text, context); |
| GeneratedMarkerVisitor.markGenerated(statement); |
| return statement; |
| } |
| |
| @NotNull |
| @Override |
| public PsiType createTypeFromText(@NotNull final String text, @Nullable final PsiElement context) throws IncorrectOperationException { |
| return createTypeInner(text, context, true); |
| } |
| |
| @NotNull |
| @Override |
| public PsiTypeParameter createTypeParameterFromText(@NotNull final String text, |
| final PsiElement context) throws IncorrectOperationException { |
| final PsiTypeParameter typeParameter = super.createTypeParameterFromText(text, context); |
| GeneratedMarkerVisitor.markGenerated(typeParameter); |
| return typeParameter; |
| } |
| |
| @NotNull |
| @Override |
| public PsiMethod createMethodFromText(@NotNull final String text, |
| final PsiElement context, |
| final LanguageLevel level) throws IncorrectOperationException { |
| final PsiMethod method = super.createMethodFromText(text, context, level); |
| GeneratedMarkerVisitor.markGenerated(method); |
| return method; |
| } |
| |
| private static PsiImportStatementBase extractImport(final PsiJavaFile aFile, final boolean isStatic) { |
| final PsiImportList importList = aFile.getImportList(); |
| assert importList != null : aFile; |
| final PsiImportStatementBase[] statements = isStatic ? importList.getImportStaticStatements() : importList.getImportStatements(); |
| assert statements.length == 1 : aFile.getText(); |
| return statements[0]; |
| } |
| |
| private static final JavaParserUtil.ParserWrapper CATCH_SECTION = new JavaParserUtil.ParserWrapper() { |
| @Override |
| public void parse(final PsiBuilder builder) { |
| JavaParser.INSTANCE.getStatementParser().parseCatchBlock(builder); |
| } |
| }; |
| |
| @NotNull |
| @Override |
| public PsiCatchSection createCatchSection(@NotNull final PsiType exceptionType, |
| @NotNull final String exceptionName, |
| @Nullable final PsiElement context) throws IncorrectOperationException { |
| if (!(exceptionType instanceof PsiClassType || exceptionType instanceof PsiDisjunctionType)) { |
| throw new IncorrectOperationException("Unexpected type:" + exceptionType); |
| } |
| |
| @NonNls final String text = "catch (" + exceptionType.getCanonicalText(true) + " " + exceptionName + ") {}"; |
| final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CATCH_SECTION, level(context)), context); |
| final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode()); |
| if (!(element instanceof PsiCatchSection)) { |
| throw new IncorrectOperationException("Incorrect catch section '" + text + "'. Parsed element: " + element); |
| } |
| |
| final Project project = myManager.getProject(); |
| final JavaPsiImplementationHelper helper = JavaPsiImplementationHelper.getInstance(project); |
| helper.setupCatchBlock(exceptionName, exceptionType, context, (PsiCatchSection)element); |
| final CodeStyleManager styleManager = CodeStyleManager.getInstance(project); |
| final PsiCatchSection catchSection = (PsiCatchSection)styleManager.reformat(element); |
| |
| GeneratedMarkerVisitor.markGenerated(catchSection); |
| return catchSection; |
| } |
| |
| @Override |
| public boolean isValidClassName(@NotNull String name) { |
| return isIdentifier(name); |
| } |
| |
| @Override |
| public boolean isValidMethodName(@NotNull String name) { |
| return isIdentifier(name); |
| } |
| |
| @Override |
| public boolean isValidParameterName(@NotNull String name) { |
| return isIdentifier(name); |
| } |
| |
| @Override |
| public boolean isValidFieldName(@NotNull String name) { |
| return isIdentifier(name); |
| } |
| |
| @Override |
| public boolean isValidLocalVariableName(@NotNull String name) { |
| return isIdentifier(name); |
| } |
| |
| private boolean isIdentifier(@NotNull String name) { |
| return PsiNameHelper.getInstance(myManager.getProject()).isIdentifier(name); |
| } |
| } |