blob: 7dd68d153179814a209f4d1e9b936d64bc1a7bb1 [file] [log] [blame]
/*
* Copyright 2017 The Bazel Authors. All rights reserved.
*
* 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.google.idea.blaze.python.run;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.XSourcePosition;
import com.jetbrains.python.debugger.PyDebugSupportUtils;
import com.jetbrains.python.debugger.PyLocalPositionConverter;
import com.jetbrains.python.debugger.PyPositionConverter;
import com.jetbrains.python.debugger.PySignature;
import com.jetbrains.python.debugger.PySourcePosition;
import java.io.File;
import java.io.IOException;
import javax.annotation.Nullable;
/**
* Converts the blaze-out symlink file paths to the actual source file paths. Otherwise a copy of
* {@link PyLocalPositionConverter}
*/
public class BlazePyPositionConverter implements PyPositionConverter {
private static final Logger logger = Logger.getInstance(BlazePyPositionConverter.class);
@Override
public PySourcePosition create(String filePath, int line) {
return new PySourcePosition(convertFilePath(filePath), line) {};
}
@Override
public PySourcePosition convertToPython(XSourcePosition position) {
return new PySourcePosition(
convertFilePath(position.getFile().getPath()),
convertLocalLineToRemote(position.getFile(), position.getLine())) {};
}
@Nullable
@Override
public XSourcePosition convertFromPython(PySourcePosition position) {
return createXSourcePosition(getVirtualFile(position.getFile()), position.getLine());
}
@Override
public PySignature convertSignature(PySignature signature) {
return signature;
}
private static String convertFilePath(String filePath) {
File file = new File(filePath);
try {
return file.getCanonicalPath();
} catch (IOException e) {
logger.warn(e);
return filePath;
}
}
private static VirtualFile getVirtualFile(String filePath) {
return LocalFileSystem.getInstance().findFileByPath(filePath);
}
@Nullable
private static XSourcePosition createXSourcePosition(@Nullable VirtualFile vFile, int line) {
if (vFile != null) {
return XDebuggerUtil.getInstance()
.createPosition(vFile, convertRemoteLineToLocal(vFile, line));
} else {
return null;
}
}
/** Convert from 1- to 0-indexed line numbering, and account for continuation lines */
private static int convertLocalLineToRemote(VirtualFile file, int line) {
AccessToken lock = ApplicationManager.getApplication().acquireReadActionLock();
try {
final Document document = FileDocumentManager.getInstance().getDocument(file);
if (document != null) {
while (PyDebugSupportUtils.isContinuationLine(document, line)) {
line++;
}
}
return line + 1;
} finally {
lock.finish();
}
}
/** Convert from 0- to 1-indexed line numbering, and account for continuation lines */
private static int convertRemoteLineToLocal(final VirtualFile vFile, int line) {
final Document document =
ApplicationManager.getApplication()
.runReadAction(
new Computable<Document>() {
@Override
public Document compute() {
return FileDocumentManager.getInstance().getDocument(vFile);
}
});
line--;
if (document != null) {
while (PyDebugSupportUtils.isContinuationLine(document, line - 1)) {
line--;
}
}
return line;
}
}