/* * Copyright 2003-2013 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 jetbrains.mps.idea.java.psi.impl; import com.intellij.psi.PsiManager; import jetbrains.mps.idea.core.psi.MPSPsiNodeFactory; import jetbrains.mps.idea.core.psi.impl.MPSPsiNode; import jetbrains.mps.idea.core.psi.impl.MPSPsiRef; import jetbrains.mps.idea.java.Constants.ConceptNames; import jetbrains.mps.idea.java.psi.impl.blTypes.MPSPsiListType; import jetbrains.mps.idea.java.psi.impl.blTypes.MPSPsiMapType; import jetbrains.mps.idea.java.psi.impl.blTypes.MPSPsiSequenceType; import jetbrains.mps.idea.java.psi.impl.blTypes.MPSPsiSetType; import jetbrains.mps.idea.java.psi.impl.blTypes.MPSPsiStringType; import org.jetbrains.mps.openapi.language.SAbstractConcept; import org.jetbrains.mps.openapi.language.SConcept; import org.jetbrains.mps.openapi.model.SModelReference; import org.jetbrains.mps.openapi.model.SNodeId; import java.util.HashMap; import java.util.Map; /** * evgeny, 1/28/13 */ public class JavaMPSPsiNodeFactory implements MPSPsiNodeFactory { private static final Map<String, NodeCreator> factories = new HashMap<String, NodeCreator>(); private static final Map<String, RefCreator> refFactories = new HashMap<String, RefCreator>(); static { factories.put(ConceptNames.ClassConcept, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiClass(id, concept, containingRole, manager); } }); // TODO use MPS-generated constant value factories.put(ConceptNames.Interface, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiInterface(id, concept, containingRole, manager); } }); factories.put(ConceptNames.EnumClass, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiEnum(id, concept, containingRole, manager); } }); factories.put(ConceptNames.ClassifierType, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiClassifierType(id, concept, containingRole, manager); } }); factories.put(ConceptNames.PrimitiveType, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiPrimitiveType(id, concept, containingRole, manager); } }); NodeCreator wildCardTypeNodeCreator = new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiWildcardType(id, concept, containingRole, manager); } }; factories.put(ConceptNames.UpperBoundType, wildCardTypeNodeCreator); factories.put(ConceptNames.LowerBoundType, wildCardTypeNodeCreator); factories.put(ConceptNames.WildCardType, wildCardTypeNodeCreator); factories.put(ConceptNames.StringType, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiStringType(id, concept, containingRole, manager); } }); factories.put(ConceptNames.ArrayType, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiArrayType(id, concept, containingRole, manager); } }); factories.put(ConceptNames.VariableArityType, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiVariableArityType(id, concept, containingRole, manager); } }); factories.put(ConceptNames.ConstructorDeclaration, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiConstructor(id, concept, containingRole, manager); } }); factories.put(ConceptNames.MethodDeclaration, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiMethod(id, concept, containingRole, manager); } }); factories.put(ConceptNames.ParameterDeclaration, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiParameter(id, concept, containingRole, manager); } }); factories.put(ConceptNames.TypeVariableDeclaration, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiTypeParameter(id, concept, containingRole, manager); } }); factories.put(ConceptNames.TypeVariableReference, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiTypeParamRef(id, concept, containingRole, manager); } }); factories.put(ConceptNames.FieldDeclaration, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiField(id, concept, containingRole, manager); } }); factories.put(ConceptNames.EnumConstantDeclaration, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiEnumConstant(id, concept, containingRole, manager); } }); factories.put(ConceptNames.StaticFieldDeclaration, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiField(id, concept, containingRole, manager); } }); // collection types factories.put(ConceptNames.SequenceType, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiSequenceType(id, concept, containingRole, manager); } }); factories.put(ConceptNames.ListType, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiListType(id, concept, containingRole, manager); } }); factories.put(ConceptNames.SetType, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiSetType(id, concept, containingRole, manager); } }); factories.put(ConceptNames.MapType, new NodeCreator() { @Override public MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager) { return new MPSPsiMapType(id, concept, containingRole, manager); } }); RefCreator dotBasedRefCreator = new RefCreator() { @Override public MPSPsiRef createReferenceNode(String role, SModelReference targetModel, SNodeId targetId, PsiManager manager) { return new MPSDotBasedPsiRef(role, targetModel, targetId, manager); } @Override public MPSPsiRef createReferenceNode(String role, String referenceText, PsiManager manager) { return new MPSDotBasedPsiRef(role, referenceText, manager); } }; RefCreator methodRefCreator = new RefCreator() { @Override public MPSPsiRef createReferenceNode(String role, SModelReference targetModel, SNodeId targetId, PsiManager manager) { return new MPSPsiMethodRef(role, targetModel, targetId, manager); } @Override public MPSPsiRef createReferenceNode(String role, String referenceText, PsiManager manager) { return new MPSPsiMethodRef(role, referenceText, manager); } }; refFactories.put(ConceptNames.Classifier, dotBasedRefCreator); refFactories.put(ConceptNames.VariableDeclaration, dotBasedRefCreator); // this is really for constructors (not all BaseMethodDeclarations) // it's done this way because currently Creators have link to ConstructorDeclaration // in a form of specialized link to BaseMethodDeclaration refFactories.put(ConceptNames.BaseMethodDeclaration, methodRefCreator); } @Override public MPSPsiNode create(SNodeId id, SConcept concept, String containingRole, PsiManager manager) { SConcept currConcept = concept; NodeCreator factory = null; while (factory == null && currConcept != null) { factory = factories.get(currConcept.getQualifiedName()); currConcept = currConcept.getSuperConcept(); } if (factory != null) { return factory.create(id, concept.getQualifiedName(), containingRole, manager); } return null; } private RefCreator getRefCreator(SAbstractConcept linkTargetConcept) { // if it's not SConcept (supposedly SInterfaceConcept) then we don't walk up the hierarchy if (!(linkTargetConcept instanceof SConcept)) { return refFactories.get(linkTargetConcept.getQualifiedName()); } SConcept currConcept = (SConcept) linkTargetConcept; RefCreator factory = null; while (factory == null && currConcept != null) { factory = refFactories.get(currConcept.getQualifiedName()); currConcept = currConcept.getSuperConcept(); } return factory; } @Override public MPSPsiRef createReferenceNode(String role, SAbstractConcept linkTargetConcept, SModelReference targetModel, SNodeId targetId, PsiManager manager) { RefCreator factory = getRefCreator(linkTargetConcept); if (factory != null) { return factory.createReferenceNode(role, targetModel, targetId, manager); } return null; } @Override public MPSPsiRef createReferenceNode(String role, SAbstractConcept linkTargetConcept, String referenceText, PsiManager manager) { RefCreator factory = getRefCreator(linkTargetConcept); if (factory != null) { return factory.createReferenceNode(role, referenceText, manager); } return null; } private interface NodeCreator { MPSPsiNode create(SNodeId id, String concept, String containingRole, PsiManager manager); } private interface RefCreator { MPSPsiRef createReferenceNode(String role, SModelReference targetModel, SNodeId targetId, PsiManager manager); MPSPsiRef createReferenceNode(String role, String referenceText, PsiManager manager); } }