File size: 5,347 Bytes
18a519f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Unity.CodeEditor;
using UnityEditor.Utils;
using UnityEngine;
namespace UnityEditor.TestTools.TestRunner.GUI
{
internal class GuiHelper : IGuiHelper
{
public GuiHelper(IMonoCecilHelper monoCecilHelper, IAssetsDatabaseHelper assetsDatabaseHelper)
{
MonoCecilHelper = monoCecilHelper;
AssetsDatabaseHelper = assetsDatabaseHelper;
GetCSFiles = (dirPath, fileExtension) =>
{
return Directory.GetFiles(dirPath, $"*{fileExtension}", SearchOption.AllDirectories)
.Select(Paths.UnifyDirectorySeparator);
};
}
internal Func<string, string, IEnumerable<string>> GetCSFiles;
protected IMonoCecilHelper MonoCecilHelper { get; private set; }
public IAssetsDatabaseHelper AssetsDatabaseHelper { get; private set; }
public IExternalCodeEditor Editor { get; internal set; }
private const string FileExtension = ".cs";
public void OpenScriptInExternalEditor(Type type, MethodInfo method)
{
var fileOpenInfo = GetFileOpenInfo(type, method);
if (string.IsNullOrEmpty(fileOpenInfo.FilePath))
{
Debug.LogWarning("Failed to open test method source code in external editor. Inconsistent filename and yield return operator in target method.");
return;
}
if (fileOpenInfo.LineNumber == 1)
{
Debug.LogWarning("Failed to get a line number for unity test method. So please find it in opened file in external editor.");
}
if (!fileOpenInfo.FilePath.Contains("Assets"))
{
(Editor ?? CodeEditor.CurrentEditor).OpenProject(fileOpenInfo.FilePath, fileOpenInfo.LineNumber, 1);
}
else
{
AssetsDatabaseHelper.OpenAssetInItsDefaultExternalEditor(fileOpenInfo.FilePath, fileOpenInfo.LineNumber);
}
}
public IFileOpenInfo GetFileOpenInfo(Type type, MethodInfo method)
{
var fileOpenInfo = MonoCecilHelper.TryGetCecilFileOpenInfo(type, method);
if (string.IsNullOrEmpty(fileOpenInfo.FilePath))
{
var dirPath = Paths.UnifyDirectorySeparator(Application.dataPath);
var allCsFiles = GetCSFiles(dirPath, FileExtension);
var fileName = allCsFiles.FirstOrDefault(x =>
x.Split(Path.DirectorySeparatorChar).Last().Equals(string.Concat(GetTestFileName(type), FileExtension)));
fileOpenInfo.FilePath = fileName ?? string.Empty;
}
if (!fileOpenInfo.FilePath.Contains("Assets"))
{
return fileOpenInfo;
}
fileOpenInfo.FilePath = FilePathToAssetsRelativeAndUnified(fileOpenInfo.FilePath);
return fileOpenInfo;
}
internal static string GetTestFileName(Type type)
{
//This handles the case of a test in a nested class, getting the name of the base class
if (type.FullName != null && type.Namespace!=null && type.FullName.Contains("+"))
{
var removedNamespace = type.FullName.Substring(type.Namespace.Length+1);
return removedNamespace.Substring(0,removedNamespace.IndexOf("+", StringComparison.Ordinal));
}
return type.Name;
}
public string FilePathToAssetsRelativeAndUnified(string filePath)
{
if (string.IsNullOrEmpty(filePath))
return string.Empty;
filePath = Paths.UnifyDirectorySeparator(filePath);
var length = Paths.UnifyDirectorySeparator(Application.dataPath).Length - "Assets".Length;
return filePath.Substring(length);
}
public bool OpenScriptInExternalEditor(string stacktrace)
{
if (string.IsNullOrEmpty(stacktrace))
return false;
var regex = new Regex("in (?<path>.*):{1}(?<line>[0-9]+)");
var matchingLines = stacktrace.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Where(x => regex.IsMatch(x)).ToList();
if (!matchingLines.Any())
return false;
var fileOpenInfos = matchingLines
.Select(x => regex.Match(x))
.Select(x =>
new FileOpenInfo
{
FilePath = x.Groups["path"].Value,
LineNumber = int.Parse(x.Groups["line"].Value)
}).ToList();
var fileOpenInfo = fileOpenInfos
.FirstOrDefault(openInfo => !string.IsNullOrEmpty(openInfo.FilePath) && File.Exists(openInfo.FilePath));
if (fileOpenInfo == null)
{
return false;
}
var filePath = FilePathToAssetsRelativeAndUnified(fileOpenInfo.FilePath);
AssetsDatabaseHelper.OpenAssetInItsDefaultExternalEditor(filePath, fileOpenInfo.LineNumber);
return true;
}
}
}
|