/* * Copyright 2003-2016 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.trace; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import jetbrains.mps.ide.project.ProjectHelper; import jetbrains.mps.project.facets.JavaModuleFacet; import jetbrains.mps.smodel.ModelAccessHelper; import jetbrains.mps.textgen.trace.BaseLanguageNodeLookup; import jetbrains.mps.textgen.trace.DefaultTraceInfoProvider; import jetbrains.mps.textgen.trace.DebugInfo; import jetbrains.mps.textgen.trace.NodeTraceInfo; import jetbrains.mps.textgen.trace.TraceInfoCache; import jetbrains.mps.textgen.trace.TraceablePositionInfo; import jetbrains.mps.util.Computable; import jetbrains.mps.util.NameUtil; import jetbrains.mps.vfs.IFile; import org.jetbrains.annotations.Nullable; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.SModelReference; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.model.SNodeReference; import org.jetbrains.mps.openapi.module.SModule; import org.jetbrains.mps.openapi.module.SRepository; import java.util.Optional; import java.util.stream.Stream; /** * Use this class for mapping debugger position (type, file, line number) to * some stuff as: node, psi file. */ public class GeneratedSourcePosition { private final SNodeReference myNode; private final String myTypeName; private final String myFileName; private final int myLineNumber; /*package*/ GeneratedSourcePosition(@Nullable SNodeReference nodeRef, String typeName, String fileName, int lineNumber) { myNode = nodeRef; myLineNumber = lineNumber; myFileName = fileName; myTypeName = typeName; } public String getTypeName() { return myTypeName; } public String getFileName() { return myFileName; } public int getLineNumber() { return myLineNumber; } @Nullable public SNodeReference getNode() { return myNode; } @Nullable public PsiFile getPsiFile(Project project) { return myNode == null ? null : getPsiFile(project, myNode.getModelReference(), myFileName); } @Nullable public static GeneratedSourcePosition fromNode(final SNode node) { NodeTraceInfo nti = new NodeTraceInfo(node, TraceInfoCache.getInstance().get(node.getModel())); TraceablePositionInfo position = nti.getPosition(); if (position == null) { return null; } return new GeneratedSourcePosition(node.getReference(), nti.getUnitName(), nti.getFileName(), position.getStartLine()); } public static GeneratedSourcePosition fromLocation(Project project, String unitName, String fileName, int line) { Optional<DebugInfo> di = new DefaultTraceInfoProvider(ProjectHelper.getProjectRepository(project)).debugInfo(NameUtil.namespaceFromLongName(unitName)).findFirst(); return new GeneratedSourcePosition(!di.isPresent() ? null : new BaseLanguageNodeLookup(di.get()).getNodeAt(fileName, line), unitName, fileName, line); } @Nullable public static PsiFile getPsiFile(final Project project, final SModelReference modelReference, final String generatedFileName) { SRepository repository = ProjectHelper.getProjectRepository(project); final String fullPath = new ModelAccessHelper(repository.getModelAccess()).runReadAction(new Computable<String>() { @Override public String compute() { SModel modelDescriptor = modelReference.resolve(repository); SModule module = modelDescriptor.getModule(); IFile defaultOutputDir = module.getFacet(JavaModuleFacet.class).getOutputLocation(modelDescriptor); IFile file = defaultOutputDir.getDescendant(generatedFileName); if (!file.exists()) { return null; } return file.getPath(); } }); if (fullPath == null) { return null; } return ApplicationManager.getApplication().runReadAction(new com.intellij.openapi.util.Computable<PsiFile>() { @Override public PsiFile compute() { VirtualFile file = LocalFileSystem.getInstance().findFileByPath(fullPath); if (file == null) { return null; } return PsiManager.getInstance(project).findFile(file); } }); } }