Merge pull request #39783 from neikeq/messaging-codecompletion-localize-fix

C#: Fix completion request with case insensitive resource path
This commit is contained in:
Rémi Verschelde 2020-06-24 01:00:05 +02:00 committed by GitHub
commit 7d60a88888
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 2 deletions

View File

@ -25,8 +25,9 @@ namespace GodotTools.Core
bool rooted = path.IsAbsolutePath();
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();

View File

@ -12,6 +12,7 @@ using GodotTools.IdeMessaging;
using GodotTools.IdeMessaging.Requests;
using GodotTools.IdeMessaging.Utils;
using GodotTools.Internals;
using GodotTools.Utils;
using Newtonsoft.Json;
using Directory = System.IO.Directory;
using File = System.IO.File;
@ -362,8 +363,13 @@ namespace GodotTools.Ides
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};
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;
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.IO;
using Godot;
using GodotTools.Core;
using JetBrains.Annotations;
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);
}
}
}