Skip to content

feat: add support for shared drive uri resolution #2234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clients/cobol-lsp-vscode-extension/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jest.mock("vscode", () => ({
file: jest.fn().mockImplementation((str: string) => {
return {
fsPath: str,
toString: jest.fn().mockReturnValue(str),
};
}),
},
Expand Down
15 changes: 6 additions & 9 deletions clients/cobol-lsp-vscode-extension/src/services/util/FSUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import * as urlUtil from "url";
import { SettingsUtils } from "./SettingsUtils";
import { Uri } from "vscode";
import * as vscode from "vscode";
import { Utils } from "./Utils";

/**
* This method is responsible to return a valid URI without extension if the extension is not provided or an URI
Expand Down Expand Up @@ -89,20 +90,16 @@ export function searchCopybookInWorkspace(
copybookFolders: string[] | undefined,
extensions: string[] | undefined,
): string | undefined {
for (const workspaceFolderPath of SettingsUtils.getWorkspaceFoldersPath()) {
for (const workspaceFolderPath of SettingsUtils.getWorkspaceFoldersPath(
true,
)) {
if (!copybookFolders || !extensions) return undefined;
const workspaceFolder = cleanWorkspaceFolder(workspaceFolderPath);
for (const p of copybookFolders) {
for (const ext of extensions) {
const searchResult = globSearch(workspaceFolder, p, copybookName, ext);
if (searchResult) {
const root = path.parse(searchResult).root;
const urlPath = searchResult
.substring(root.length)
.split(path.sep)
.map((s) => encodeURIComponent(s))
.join(path.sep);
return new urlUtil.URL("file://" + root + urlPath).href;
return vscode.Uri.file(searchResult).toString();
}
}
}
Expand Down Expand Up @@ -144,7 +141,7 @@ function globSearch(
.replace(backwardSlashRegex, "/");
const normalizePathName = pathName.replace(backwardSlashRegex, "/");
let pattern =
normalizePathName === cwd
normalizePathName === cwd && !Utils.isUNCPath(normalizePathName)
? ""
: normalizePathName.replace(cwd.endsWith("/") ? cwd : cwd + "/", "");
const suffix =
Expand Down
17 changes: 17 additions & 0 deletions clients/cobol-lsp-vscode-extension/src/services/util/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ export class Utils {
return content === null || content === undefined;
}

/**
* Based on below refrences
* Ref : https://stackoverflow.com/questions/6344936/validation-of-unc-path-using-javascript
* Ref : https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/62e862f4-2a51-452e-8eeb-dc4ff5ee33cc?redirectedfrom=MSDN
*/
private static UNC_PATH_REGEX =
/^\\\\([^\\:\|\[\]\/";<>+=,?* _]+)\\([\u0020-\u0021\u0023-\u0029\u002D-\u002E\u0030-\u0039\u0040-\u005A\u005E-\u007B\u007E-\u00FF]{1,80})(((?:\\[\u0020-\u0021\u0023-\u0029\u002D-\u002E\u0030-\u0039\u0040-\u005A\u005E-\u007B\u007E-\u00FF]{1,255})+?|)(?:\\((?:[\u0020-\u0021\u0023-\u0029\u002B-\u002E\u0030-\u0039\u003B\u003D\u0040-\u005B\u005D-\u007B]{1,255}){1}(?:\:(?=[\u0001-\u002E\u0030-\u0039\u003B-\u005B\u005D-\u00FF]|\:)(?:([\u0001-\u002E\u0030-\u0039\u003B-\u005B\u005D-\u00FF]+(?!\:)|[\u0001-\u002E\u0030-\u0039\u003B-\u005B\u005D-\u00FF]*)(?:\:([\u0001-\u002E\u0030-\u0039\u003B-\u005B\u005D-\u00FF]+)|))|)))|)$/;

public static async getZoweExplorerAPI(): Promise<IApiRegisterClient> {
const ext = vscode.extensions.getExtension(
"Zowe.vscode-extension-for-zowe",
Expand All @@ -40,4 +48,13 @@ export class Utils {
await ext.activate();
return ext.exports as any;
}

/**
* Checks is a path is a UNC path
* @param path to be checked
* @returns true if passed path is UNC path, false otherwise
*/
public static isUNCPath(path: string) {
return this.UNC_PATH_REGEX.test(path);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ suite("Tests with USER1.cbl", function () {
);
assert.strictEqual(result.length, 1);
assert.ok(
result[0].uri.fsPath === editor.document.fileName &&
result[0].uri.fsPath.includes(editor.document.fileName) &&
result[0].range.start.line === 31 &&
result[0].range.start.character === 7,
"Checks behavior of go to definition action",
Expand All @@ -78,7 +78,7 @@ suite("Tests with USER1.cbl", function () {
);
assert.ok(
result.length === 3 &&
result[0].uri.fsPath === editor.document.fileName &&
result[0].uri.fsPath.includes(editor.document.fileName) &&
result[0].range.start.line === 20 &&
result[1].range.start.line === 34 &&
result[2].range.start.line === 42,
Expand All @@ -94,7 +94,7 @@ suite("Tests with USER1.cbl", function () {
);
assert.ok(
result.length === 3 &&
result[0].uri.fsPath === editor.document.fileName &&
result[0].uri.fsPath.includes(editor.document.fileName) &&
result[0].range.start.line === 20 &&
result[1].range.start.line === 34 &&
result[2].range.start.line === 42,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@
package org.eclipse.lsp.cobol.common.file;

import com.google.common.collect.ImmutableList;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.lsp.cobol.common.utils.ImplicitCodeUtils;

import javax.annotation.Nullable;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -37,6 +32,10 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.lsp.cobol.common.utils.ImplicitCodeUtils;

/**
* This service implements API for low-level file systems access. It mainly oriented to work with
Expand Down Expand Up @@ -94,7 +93,12 @@ public String getContentByPath(@NonNull Path path) {
@Nullable
public Path getPathFromURI(@NonNull String uri) {
try {
return Paths.get(new URI(uri).normalize());
String decodedUri = uri.replace(" ", "%20");
Path path = Paths.get(new URI(decodedUri).normalize());
if (path.startsWith("\\") || path.startsWith("/")) {
path = Paths.get(new URI(decodedUri).getPath()); //
}
return path;
} catch (URISyntaxException e) {
LOG.error("Cannot find file by given URI: {}", uri, e);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
package org.eclipse.lsp.cobol.common.model.tree;

import com.google.common.collect.ImmutableList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
Expand All @@ -23,10 +26,6 @@
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;

import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

/** The class represents the copyBookNode. */
@ToString(callSuper = true)
@Getter
Expand Down Expand Up @@ -54,7 +53,8 @@ public CopyNode(Locality statementLocality, Location nameLocation, String copyBo

@Override
public List<Location> getDefinitions() {
return Optional.ofNullable(uri).map(u -> ImmutableList.of(new Location(u, new Range(new Position(), new Position()))))
return Optional.ofNullable(uri)
.map(u -> ImmutableList.of(new Location(u, new Range(new Position(), new Position()))))
.orElse(ImmutableList.of());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@

package org.eclipse.lsp.cobol.dialects.idms.usecases;

import static org.eclipse.lsp4j.DiagnosticSeverity.Warning;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.lsp.cobol.common.AnalysisResult;
import org.eclipse.lsp.cobol.common.error.ErrorSource;
import org.eclipse.lsp.cobol.common.model.tree.ProgramNode;
Expand All @@ -35,12 +40,6 @@
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static org.eclipse.lsp4j.DiagnosticSeverity.Warning;

/** Test the variables for IDMS copybooks are not modified if adjusted levels are greater than 48 */
public class TestCopyIdmsVariablesForNotAllowedLevels {

Expand Down Expand Up @@ -113,7 +112,7 @@ void noAdjustmentWhenAdjustedLevelGreaterThan49() {
Collections.singletonList(
new DiagnosticRelatedInformation(
new Location(
"file:///c:/workspace/document.cbl",
"file:c:/workspace/document.cbl",
new Range(new Position(9, 11), new Position(9, 29))),
"Copy IDMS source")));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
Expand Down Expand Up @@ -128,9 +130,9 @@ private void updateGraphLink(CobolDocumentModel model, EventSource eventSource)
});
objectRef.putIfAbsent(copyNode.getUri(), copyNodeV);
references.add(copyNodeV);

documentGraphIndexedByCopybook.putIfAbsent(copyNode.getUri(), new ArrayList<>());
List<String> strings = documentGraphIndexedByCopybook.get(copyNode.getUri());
String decodedUri = uriDecodeService.decode(copyNode.getUri());
documentGraphIndexedByCopybook.putIfAbsent(decodedUri, new ArrayList<>());
List<String> strings = documentGraphIndexedByCopybook.get(decodedUri);
if (!strings.contains(parentUri)) {
strings.add(parentUri);
}
Expand Down Expand Up @@ -176,7 +178,16 @@ private void invalidateCopybookIndexedCache(String referUri, String copybookUri)
* @return true if copybook, false otherwise.
*/
public boolean isCopybook(String uri) {
return documentGraphIndexedByCopybook.containsKey(uri);
return documentGraphIndexedByCopybook.keySet().stream().anyMatch(copyUri -> {
try {
String decodeUri = uri.replace(" ", "%20");
copyUri = copyUri.replace(" ", "%20");
return new URL(decodeUri).sameFile(new URL(copyUri));
} catch (IOException e) {
LOG.error("IOException encountered while comparing paths {} and {}", copyUri, uri);
return false;
}
});
}

private void updateGraphNodes(CobolDocumentModel model, EventSource eventSource) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.eclipse.lsp.cobol.core.preprocessor.TextPreprocessor;
import org.eclipse.lsp.cobol.core.semantics.CopybooksRepository;
import org.eclipse.lsp.cobol.lsp.jrpc.CobolLanguageClient;
import org.eclipse.lsp.cobol.service.UriDecodeService;

/**
* This service processes copybook requests and returns content by its name. The service also caches
Expand All @@ -56,6 +57,7 @@ public class CopybookServiceImpl implements CopybookService {
private final Map<String, List<SyntaxError>> preprocessCopybookErrors = new ConcurrentHashMap<>();
private final Map<String, Set<CopybookModel>> copybookUsage = new ConcurrentHashMap<>();
private final Provider<CobolLanguageClient> clientProvider;
private final UriDecodeService uriDecodeService;
private final FileSystemService files;
public final TextPreprocessor preprocessor;
private static final String COBOL = "COBOL";
Expand All @@ -69,11 +71,13 @@ public class CopybookServiceImpl implements CopybookService {
public CopybookServiceImpl(Provider<CobolLanguageClient> clientProvider,
FileSystemService files,
TextPreprocessor preprocessor,
CopybookCache copybookCache) {
CopybookCache copybookCache,
UriDecodeService uriDecodeService) {
this.files = files;
this.clientProvider = clientProvider;
this.preprocessor = preprocessor;
this.copybookCache = copybookCache;
this.uriDecodeService = uriDecodeService;
}

@Override
Expand Down Expand Up @@ -223,7 +227,7 @@ private Optional<CopybookModel> tryResolveCopybookFromWorkspace(

final Optional<CopybookModel> copybookModel =
resolveCopybookFromWorkspace(copybookName, programUri)
.map(uri -> loadCopybook(uri, copybookName, programUri));
.map(uri -> loadCopybook(uri, copybookName, programUri));
LOG.debug("Copybook from workspace: {}", copybookModel);
return copybookModel;
}
Expand Down Expand Up @@ -260,9 +264,9 @@ private CopybookModel registerForDownloading(CopybookName copybookName, String p

private CopybookModel loadCopybook(String uri, CopybookName copybookName, String programUri) {
Path file = files.getPathFromURI(uri);
LOG.debug("Loading {} with URI {} for {} from path {}", copybookName, uri, files.getNameFromURI(programUri), file);
LOG.debug("Loading {} with URI {} for {} from path {}", copybookName, uriDecodeService.decode(uri), files.getNameFromURI(programUri), file);
return files.fileExists(file)
? new CopybookModel(copybookName.toCopybookId(programUri), copybookName, uri, files.getContentByPath(Objects.requireNonNull(file)))
? new CopybookModel(copybookName.toCopybookId(programUri), copybookName, uriDecodeService.decode(uri), files.getContentByPath(Objects.requireNonNull(file)))
: registerForDownloading(copybookName, programUri);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class SourceUnitGraphTest {
public static final String URI = "file://document.cbl";
@Mock private WorkspaceFileService fileService;
@Mock private AsyncAnalysisService asyncAnalysisService;
@Mock private UriDecodeService uriDecodeService;
private final UriDecodeService uriDecodeService = new UriDecodeService();

@Test
void testNotifyState() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.lsp.cobol.common.utils.PredefinedCopybooks;
import org.eclipse.lsp.cobol.core.preprocessor.TextPreprocessor;
import org.eclipse.lsp.cobol.lsp.jrpc.CobolLanguageClient;
import org.eclipse.lsp.cobol.service.UriDecodeService;
import org.eclipse.lsp.cobol.service.providers.ClientProvider;
import org.eclipse.lsp4j.services.LanguageClient;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -68,6 +69,7 @@ class CopybookServiceTest {
private final TextPreprocessor preprocessor = mock(TextPreprocessor.class);
private final Path cpyPath = mock(Path.class);
private final Path parentPath = mock(Path.class);
private UriDecodeService uriDecodeService = new UriDecodeService();

@BeforeEach
void setupMocks() throws IOException {
Expand Down Expand Up @@ -486,7 +488,7 @@ private CopybookServiceImpl createCopybookService() {
ClientProvider provider = new ClientProvider();
provider.setClient(client);
return new CopybookServiceImpl(
provider, files, preprocessor, new CopybookCache(3, 3, "HOURS"));
provider, files, preprocessor, new CopybookCache(3, 3, "HOURS"), uriDecodeService);
}

private CopybookName createCopybook(String displayName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
*/
package org.eclipse.lsp.cobol.usecases;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.Optional;
import org.eclipse.lsp.cobol.common.AnalysisResult;
import org.eclipse.lsp.cobol.common.error.ErrorSource;
import org.eclipse.lsp.cobol.common.model.Locality;
Expand All @@ -28,11 +32,6 @@
import org.eclipse.lsp4j.Range;
import org.junit.jupiter.api.Test;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

/** The test for various cases with the continuation line */
class TestContinuationLine {
private static final String TEXT =
Expand Down Expand Up @@ -146,7 +145,7 @@ void testWhenContinuousLineStartsWithTwoQuotes_thenTwoLiteralsAreIdentified() {

assertTrue(node.isPresent());
assertEquals(Locality.builder()
.uri("file:///c:/workspace/document.cbl")
.uri("file:c:/workspace/document.cbl")
.range(new Range(new Position(8, 7), new Position(13, 44)))
.build(), node.get().getLocality());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void test() {
ImmutableList.of(),
ImmutableMap.of(
"1",
new Diagnostic(new Range(), "TESTDIALECT dialect is missing (required for file:///c:/workspace/document.cbl)", DiagnosticSeverity.Error, ErrorSource.DIALECT.getText())),
new Diagnostic(new Range(), "TESTDIALECT dialect is missing (required for file:c:/workspace/document.cbl)", DiagnosticSeverity.Error, ErrorSource.DIALECT.getText())),
ImmutableList.of(),
new AnalysisConfig(CopybookProcessingMode.ENABLED,
ImmutableList.of("TESTDIALECT"), false, ImmutableList.of(), ImmutableMap.of()));
Expand Down
Loading
Loading