[3.2] C#: Fix completion request with case insensitive resource path
Sometimes Visual Studio documents have the root path all in upper case. Since Godot doesn't support loading resource files with a case insensitive path, this makes script resource loading to fail when the Godot editor gets code completion requests from Visual Studio. This fix allows the resource path part of the path to be case insensitive. It still doesn't support cases where the rest of the path is also case insensitive. For that we would need a proper API for comparing paths. However, this fix should be enough for our current cases.
This commit is contained in:
parent
d8af79140e
commit
d0f365fe0f
|
@ -25,8 +25,9 @@ namespace GodotTools.Core
|
||||||
bool rooted = path.IsAbsolutePath();
|
bool rooted = path.IsAbsolutePath();
|
||||||
|
|
||||||
path = path.Replace('\\', '/');
|
path = path.Replace('\\', '/');
|
||||||
|
path = path[path.Length - 1] == '/' ? path.Substring(0, path.Length - 1) : path;
|
||||||
|
|
||||||
string[] parts = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
string[] parts = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
path = string.Join(Path.DirectorySeparatorChar.ToString(), parts).Trim();
|
path = string.Join(Path.DirectorySeparatorChar.ToString(), parts).Trim();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ using GodotTools.IdeMessaging;
|
||||||
using GodotTools.IdeMessaging.Requests;
|
using GodotTools.IdeMessaging.Requests;
|
||||||
using GodotTools.IdeMessaging.Utils;
|
using GodotTools.IdeMessaging.Utils;
|
||||||
using GodotTools.Internals;
|
using GodotTools.Internals;
|
||||||
|
using GodotTools.Utils;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Directory = System.IO.Directory;
|
using Directory = System.IO.Directory;
|
||||||
using File = System.IO.File;
|
using File = System.IO.File;
|
||||||
|
@ -362,8 +363,13 @@ namespace GodotTools.Ides
|
||||||
|
|
||||||
private static async Task<Response> HandleCodeCompletionRequest(CodeCompletionRequest request)
|
private static async Task<Response> HandleCodeCompletionRequest(CodeCompletionRequest request)
|
||||||
{
|
{
|
||||||
|
// This is needed if the "resource path" part of the path is case insensitive.
|
||||||
|
// However, it doesn't fix resource loading if the rest of the path is also case insensitive.
|
||||||
|
string scriptFileLocalized = FsPathUtils.LocalizePathWithCaseChecked(request.ScriptFile);
|
||||||
|
|
||||||
var response = new CodeCompletionResponse {Kind = request.Kind, ScriptFile = request.ScriptFile};
|
var response = new CodeCompletionResponse {Kind = request.Kind, ScriptFile = request.ScriptFile};
|
||||||
response.Suggestions = await Task.Run(() => Internal.CodeCompletionRequest(response.Kind, response.ScriptFile));
|
response.Suggestions = await Task.Run(() =>
|
||||||
|
Internal.CodeCompletionRequest(response.Kind, scriptFileLocalized ?? request.ScriptFile));
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
using System;
|
||||||
|
using Godot;
|
||||||
|
using GodotTools.Core;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Path = System.IO.Path;
|
||||||
|
|
||||||
|
namespace GodotTools.Utils
|
||||||
|
{
|
||||||
|
public static class FsPathUtils
|
||||||
|
{
|
||||||
|
private static readonly string ResourcePath = ProjectSettings.GlobalizePath("res://");
|
||||||
|
|
||||||
|
private static bool PathStartsWithAlreadyNorm(this string childPath, string parentPath)
|
||||||
|
{
|
||||||
|
// This won't work for Linux/macOS case insensitive file systems, but it's enough for our current problems
|
||||||
|
bool caseSensitive = !OS.IsWindows;
|
||||||
|
|
||||||
|
string parentPathNorm = parentPath.NormalizePath() + Path.DirectorySeparatorChar;
|
||||||
|
string childPathNorm = childPath.NormalizePath() + Path.DirectorySeparatorChar;
|
||||||
|
|
||||||
|
return childPathNorm.StartsWith(parentPathNorm,
|
||||||
|
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool PathStartsWith(this string childPath, string parentPath)
|
||||||
|
{
|
||||||
|
string childPathNorm = childPath.NormalizePath() + Path.DirectorySeparatorChar;
|
||||||
|
string parentPathNorm = parentPath.NormalizePath() + Path.DirectorySeparatorChar;
|
||||||
|
|
||||||
|
return childPathNorm.PathStartsWithAlreadyNorm(parentPathNorm);
|
||||||
|
}
|
||||||
|
|
||||||
|
[CanBeNull]
|
||||||
|
public static string LocalizePathWithCaseChecked(string path)
|
||||||
|
{
|
||||||
|
string pathNorm = path.NormalizePath() + Path.DirectorySeparatorChar;
|
||||||
|
string resourcePathNorm = ResourcePath.NormalizePath() + Path.DirectorySeparatorChar;
|
||||||
|
|
||||||
|
if (!pathNorm.PathStartsWithAlreadyNorm(resourcePathNorm))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string result = "res://" + pathNorm.Substring(resourcePathNorm.Length);
|
||||||
|
|
||||||
|
// Remove the last separator we added
|
||||||
|
return result.Substring(0, result.Length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue