From 8f3969125a5af9cb3db3f1741e6d443c1dddb07a Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 14 Sep 2022 12:21:02 -0400 Subject: [PATCH] Do not complete paths in attr unless beginning of value looks like a path Fixes redhat-developer/vscode-xml#668 Signed-off-by: David Thompson --- .../FilePathCompletionParticipant.java | 34 +++++++++-- .../lemminx/AbstractCacheBasedTest.java | 1 - .../general/FilePathCompletionTest.java | 61 ++++++++++--------- 3 files changed, 62 insertions(+), 34 deletions(-) diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/general/completion/FilePathCompletionParticipant.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/general/completion/FilePathCompletionParticipant.java index df8af4e812..d996c56de3 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/general/completion/FilePathCompletionParticipant.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/general/completion/FilePathCompletionParticipant.java @@ -77,20 +77,20 @@ public class FilePathCompletionParticipant extends CompletionParticipantAdapter public void onAttributeValue(String value, ICompletionRequest request, ICompletionResponse response, CancelChecker cancelChecker) throws Exception { // File path completion on attribute value - addCompletionItems(value, request, response); + addCompletionItems(value, request, response, false); } @Override public void onDTDSystemId(String value, ICompletionRequest request, ICompletionResponse response, CancelChecker cancelChecker) throws Exception { // File path completion on DTD DOCTYPE SYSTEM - addCompletionItems(value, request, response); + addCompletionItems(value, request, response, true); } - private static void addCompletionItems(String value, ICompletionRequest request, ICompletionResponse response) + private static void addCompletionItems(String value, ICompletionRequest request, ICompletionResponse response, boolean isInDoctype) throws Exception { String fullValue = value; - if (isEmpty(fullValue)) { + if (isEmpty(fullValue) && !isInDoctype) { return; } @@ -101,7 +101,7 @@ private static void addCompletionItems(String value, ICompletionRequest request, // ex value="file:///C:/fold|er" int valuePathStartOffset = xmlDocument.offsetAt(request.getReplaceRange().getStart()); int endPathOffset = request.getOffset(); // offset after the typed character - int startPathOffset = StringUtils.getOffsetAfterWhitespace(fullValue, endPathOffset - valuePathStartOffset) + int startPathOffset = (fullValue.length() == 0 ? 0 : StringUtils.getOffsetAfterWhitespace(fullValue, endPathOffset - valuePathStartOffset)) + valuePathStartOffset; // first character of URI Range filePathRange = XMLPositionUtility.createRange(startPathOffset, endPathOffset, xmlDocument); String originalValuePath = text.substring(startPathOffset, endPathOffset); @@ -132,6 +132,9 @@ private static void addCompletionItems(String value, ICompletionRequest request, return; } } + } else if (!hasPathBeginning(valuePath) && !isInDoctype) { + // the user probably didn't intend to complete a path + return; } // On Linux, Mac OS replace '\\' with '/' if (!isWindows) { @@ -259,4 +262,25 @@ private static void createFilePathCompletionItem(File f, Range replaceRange, ICo response.addCompletionItem(item); } + private static boolean hasPathBeginning(String currentText) { + if (currentText.startsWith("/") + || currentText.startsWith("./") + || currentText.startsWith("../") + || currentText.startsWith("..\\") + || currentText.startsWith(".\\")) { + return true; + } + return isAbsoluteWindowsPath(currentText); + } + + private static boolean isAbsoluteWindowsPath(String currentText) { + if (currentText.length() < 3) { + return false; + } + if (!Character.isLetter(currentText.charAt(0))) { + return false; + } + return currentText.charAt(1) == ':' && (currentText.charAt(2) == '\\' || currentText.charAt(2) == '/'); + } + } \ No newline at end of file diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/AbstractCacheBasedTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/AbstractCacheBasedTest.java index 47ff2f058c..101f2f8b5b 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/AbstractCacheBasedTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/AbstractCacheBasedTest.java @@ -45,7 +45,6 @@ public abstract class AbstractCacheBasedTest { @BeforeEach public final void setupCache() throws Exception { - System.out.println(this.getClass().getName() + ": " + uuid); clearCache(); FilesUtils.resetDeployPath(); Assertions.assertNotNull(parentDir); diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/general/FilePathCompletionTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/general/FilePathCompletionTest.java index 3e1764ff75..1179531278 100644 --- a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/general/FilePathCompletionTest.java +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/general/FilePathCompletionTest.java @@ -66,15 +66,13 @@ public void testFilePathCompletionFolderABackSlash() throws BadLocationException @Test public void testFilePathCompletionFolderB() throws BadLocationException { String xml = ""; - CompletionItem[] items = getCompletionItemList("/", 0, 16, 17, "xsdB1.xsd", "xmlB1.xml"); - testCompletionFor(xml, 2, items); + testCompletionFor(xml, 0); } @Test public void testFilePathCompletionFolderBBackSlash() throws BadLocationException { String xml = ""; - CompletionItem[] items = getCompletionItemList("\\", 0, 16, 17, "xsdB1.xsd", "xmlB1.xml"); - testCompletionFor(xml, 2, items); + testCompletionFor(xml, 0); } @Test @@ -113,44 +111,42 @@ public void testFilePathCompletionFolderBAbsolutePathWithFileScheme() throws Bad @Test public void testFilePathCompletionNestedA() throws BadLocationException { - String xml = ""; - CompletionItem[] items = getCompletionItemList("/", 0, 16, 17, "NestedB"); + String xml = ""; + CompletionItem[] items = getCompletionItemList("/", 0, 18, 19, "NestedB"); testCompletionFor(xml, 1, items); } @Test public void testFilePathCompletionNestedABackSlash() throws BadLocationException { - String xml = ""; - CompletionItem[] items = getCompletionItemList("\\", 0, 16, 17, "NestedB"); + String xml = ""; + CompletionItem[] items = getCompletionItemList("\\", 0, 18, 19, "NestedB"); testCompletionFor(xml, 1, items); } @Test public void testFilePathCompletionNestedBIncomplete() throws BadLocationException { - String xml = ""; - CompletionItem[] items = getCompletionItemList("/", 0, 24, 28, "nestedXSD.xsd"); + String xml = ""; + CompletionItem[] items = getCompletionItemList("/", 0, 26, 30, "nestedXSD.xsd"); testCompletionFor(xml, 1, items); } @Test public void testFilePathCompletionNestedBIncompleteBackSlash() throws BadLocationException { - String xml = ""; - CompletionItem[] items = getCompletionItemList("\\", 0, 24, 28, "nestedXSD.xsd"); + String xml = ""; + CompletionItem[] items = getCompletionItemList("\\", 0, 26, 30, "nestedXSD.xsd"); testCompletionFor(xml, 1, items); } @Test public void testFilePathCompletionExtraTextInValue() throws BadLocationException { String xml = ""; - CompletionItem[] items = getCompletionItemList("/", 0, 44, 45, "nestedXSD.xsd"); - testCompletionFor(xml, 1, items); + testCompletionFor(xml, 0); } @Test public void testFilePathCompletionExtraTextInValueBackSlash() throws BadLocationException { String xml = ""; - CompletionItem[] items = getCompletionItemList("\\", 0, 44, 45, "nestedXSD.xsd"); - testCompletionFor(xml, 1, items); + testCompletionFor(xml, 0); } @Test @@ -166,11 +162,8 @@ public void testFilePathCompletionExtraTextInValueAbsolute() throws BadLocationE @Test public void testFilePathCompletionExtraTextInValueAbsoluteBackSlash() throws BadLocationException { String filePath = userDirBackSlash + "\\src\\test\\resources\\filePathCompletion\\NestedA\\NestedB\\"; - int filePathLength = filePath.length(); String xml = ""; - CompletionItem[] items = getCompletionItemList("\\", 0, 29 + filePathLength - 1, 29 + filePathLength, - "nestedXSD.xsd"); - testCompletionFor(xml, 1, items); + testCompletionFor(xml, 1); } @Test @@ -262,22 +255,22 @@ public void testFilePathCompletionDTDFolderABackSlash() throws BadLocationExcept @Test public void testFilePathCompletionDTDFolderB() throws BadLocationException { - String xml = ""; - CompletionItem[] items = getCompletionItemList("/", 0, 29, 30, "xsdB1.xsd", "xmlB1.xml"); + String xml = ""; + CompletionItem[] items = getCompletionItemList("/", 0, 31, 32, "xsdB1.xsd", "xmlB1.xml"); testCompletionFor(xml, 2, items); } @Test public void testFilePathCompletionDTDFolderBBackSlash() throws BadLocationException { - String xml = ""; - CompletionItem[] items = getCompletionItemList("\\", 0, 29, 30, "xsdB1.xsd", "xmlB1.xml"); + String xml = ""; + CompletionItem[] items = getCompletionItemList("\\", 0, 31, 32, "xsdB1.xsd", "xmlB1.xml"); testCompletionFor(xml, 2, items); } @Test - public void testFilePathNoCompletion() throws BadLocationException { + public void testFilePathCompletionForEmptyDoctype() throws BadLocationException { String xml = ""; - testCompletionFor(xml, 0); + testCompletionFor(xml, 8); } @Test @@ -288,8 +281,8 @@ public void testFilePathNoCompletionMissingSystemId() throws BadLocationExceptio @Test public void testFilePathCompletionWithSpacesFolder() throws BadLocationException { - String xml = ""; - CompletionItem[] items = getCompletionItemList("/", 0, 16, 17, "a@b", "with%20spaces"); + String xml = ""; + CompletionItem[] items = getCompletionItemList("/", 0, 18, 19, "a@b", "with%20spaces"); testCompletionFor(xml, 2, items); } @@ -301,6 +294,18 @@ public void testFilePathCompletionInsideSpecialChars() throws BadLocationExcepti XMLAssert.testCompletionFor(xml, null, fileURI, 2, items); } + @Test + public void testFilePathCompletionWithBrokenAbsoluteWindowsPath() throws BadLocationException { + String xml = ""; + testCompletionFor(xml, 0); + xml = ""; + testCompletionFor(xml, 0); + xml = ""; + testCompletionFor(xml, 0); + xml = ""; + testCompletionFor(xml, 0); + } + private static void testCompletionFor(String xml, CompletionItem... expectedItems) throws BadLocationException { testCompletionFor(xml, null, expectedItems); }