/* * Copyright 2013-2017 consulo.io * * 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 consulo.csharp.lang.psi.impl.msil.transformer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import consulo.annotations.RequiredReadAction; import consulo.csharp.lang.psi.ToNativeElementTransformer; import consulo.csharp.lang.psi.impl.msil.MsilMethodAsCSharpMethodDeclaration; import consulo.csharp.lang.psi.impl.msil.MsilToCSharpUtil; import consulo.dotnet.psi.DotNetMemberOwner; import consulo.dotnet.psi.DotNetNamedElement; import consulo.msil.lang.psi.MsilClassEntry; import consulo.msil.lang.psi.MsilFile; /** * @author VISTALL * @since 15.03.2016 */ public class MsilToNativeElementTransformer implements ToNativeElementTransformer { private static final Logger LOGGER = Logger.getInstance(MsilToNativeElementTransformer.class); @RequiredReadAction @Nullable @Override public PsiElement transform(@NotNull PsiElement element) { if(element instanceof MsilClassEntry) { MsilClassEntry rootClassEntry = findRootClassEntry((MsilClassEntry) element); PsiElement wrappedElement = MsilToCSharpUtil.wrap(element, null); // we wrap it if(wrappedElement != rootClassEntry) { PsiElement elementByOriginal = findElementByOriginal(wrappedElement, element); if(elementByOriginal != null) { return elementByOriginal; } else { LOGGER.warn("We cant find by original element class: " + rootClassEntry.getVmQName() + "/" + ((MsilClassEntry) element).getVmQName()); } } } return null; } @NotNull public static MsilClassEntry findRootClassEntry(@NotNull MsilClassEntry element) { PsiFile containingFile = element.getContainingFile(); if(!(containingFile instanceof MsilFile)) { return element; } MsilClassEntry originalClassEntry = null; PsiElement temp = element; while(!(temp instanceof MsilFile)) { if(temp instanceof MsilClassEntry && temp.getParent() instanceof MsilFile) { originalClassEntry = (MsilClassEntry) temp; break; } temp = temp.getParent(); } if(originalClassEntry == null) { throw new IllegalArgumentException("Cant determinate parent msil class for: " + containingFile.getName()); } return originalClassEntry; } @Nullable public static PsiElement findElementByOriginal(@NotNull PsiElement wrappedElement, @NotNull PsiElement originalTarget) { PsiElement originalElement = wrappedElement.getOriginalElement(); if(originalElement.isEquivalentTo(originalTarget)) { return wrappedElement; } if(wrappedElement instanceof MsilMethodAsCSharpMethodDeclaration) { MsilClassEntry delegate = ((MsilMethodAsCSharpMethodDeclaration) wrappedElement).getDelegate(); if(delegate != null && delegate.isEquivalentTo(originalTarget)) { return wrappedElement; } } if(wrappedElement instanceof DotNetMemberOwner) { DotNetNamedElement[] members = ((DotNetMemberOwner) wrappedElement).getMembers(); for(DotNetNamedElement member : members) { PsiElement elementByOriginal = findElementByOriginal(member, originalTarget); if(elementByOriginal != null) { return elementByOriginal; } } } return null; } }