-
Notifications
You must be signed in to change notification settings - Fork 242
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #156 from Vidminas/fix-relpaths
Fix relative paths and schema changes
- Loading branch information
Showing
6 changed files
with
565 additions
and
287 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { URI } from 'vscode-uri'; | ||
import { IConnection } from 'vscode-languageserver'; | ||
import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light'; | ||
import fs = require('fs'); | ||
|
||
|
||
import { VSCodeContentRequest, CustomSchemaContentRequest } from '../../requestTypes'; | ||
import { isRelativePath, relativeToAbsolutePath } from '../utils/paths'; | ||
|
||
/** | ||
* Handles schema content requests given the schema URI | ||
* @param uri can be a local file, vscode request, http(s) request or a custom request | ||
*/ | ||
export const schemaRequestHandler = (connection: IConnection, uri: string): Thenable<string> => { | ||
if (!uri) { | ||
return Promise.reject('No schema specified'); | ||
} | ||
|
||
// If the requested schema URI is a relative file path | ||
// Convert it into a proper absolute path URI | ||
if (isRelativePath(uri)) { | ||
uri = relativeToAbsolutePath(this.workspaceFolders, this.workspaceRoot, uri); | ||
} | ||
|
||
const scheme = URI.parse(uri).scheme.toLowerCase(); | ||
|
||
// If the requested schema is a local file, read and return the file contents | ||
if (scheme === 'file') { | ||
const fsPath = URI.parse(uri).fsPath; | ||
|
||
return new Promise<string>((c, e) => { | ||
fs.readFile(fsPath, 'UTF-8', (err, result) => | ||
// If there was an error reading the file, return empty error message | ||
// Otherwise return the file contents as a string | ||
err ? e('') : c(result.toString()) | ||
); | ||
}); | ||
} | ||
|
||
// vscode schema content requests are forwarded to the client through LSP | ||
// This is a non-standard LSP extension introduced by the JSON language server | ||
// See https://github.com/microsoft/vscode/blob/master/extensions/json-language-features/server/README.md | ||
if (scheme === 'vscode') { | ||
return connection.sendRequest(VSCodeContentRequest.type, uri) | ||
.then(responseText => responseText, error => error.message); | ||
} | ||
|
||
// HTTP(S) requests are sent and the response result is either the schema content or an error | ||
if (scheme === 'http' || scheme === 'https') { | ||
// If it's an HTTP(S) request to Microsoft Azure, log the request | ||
if (uri.indexOf('//schema.management.azure.com/') !== -1) { | ||
connection.telemetry.logEvent({ | ||
key: 'json.schema', | ||
value: { | ||
schemaURL: uri | ||
} | ||
}); | ||
} | ||
|
||
// Send the HTTP(S) schema content request and return the result | ||
const headers = { 'Accept-Encoding': 'gzip, deflate' }; | ||
return xhr({ url: uri, followRedirects: 5, headers }) | ||
.then(response => response.responseText, | ||
(error: XHRResponse) => Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString())); | ||
} | ||
|
||
// Neither local file nor vscode, nor HTTP(S) schema request, so send it off as a custom request | ||
return connection.sendRequest(CustomSchemaContentRequest.type, uri) as Thenable<string>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { WorkspaceFolder } from 'vscode-languageserver'; | ||
import { join, normalize } from 'path'; | ||
import { URI } from 'vscode-uri'; | ||
|
||
export const isRelativePath = (path: string): boolean => { | ||
const relativePathRegex = /^(((\.\.?)|([\w-\. ]+))(\/|\\\\?))*[\w-\. ]*\.[\w-]+$/i; | ||
return relativePathRegex.test(path); | ||
}; | ||
|
||
export const relativeToAbsolutePath = (workspaceFolders: WorkspaceFolder[], workspaceRoot: URI, uri: string): string => { | ||
// Iterate through all of the workspace root folders | ||
for (const folder of workspaceFolders) { | ||
// If the requested schema URI specifies a workspace root folder | ||
// Convert it into an absolute path with the appropriate root folder path | ||
if (uri.startsWith(folder.name)) { | ||
const pathToFolder = URI.parse(folder.uri).fsPath; | ||
const withoutFolderPrefix = uri.split(folder.name); | ||
withoutFolderPrefix.shift(); | ||
|
||
return URI.file(join(pathToFolder, withoutFolderPrefix.join())).toString(); | ||
} | ||
} | ||
|
||
// If a root folder was not specified, resolve the relative URI | ||
// Against the location of the workspace file instead | ||
if (workspaceRoot) { | ||
return URI.file(join(workspaceRoot.fsPath, uri)).toString(); | ||
} | ||
|
||
// Fallback in case nothing could be applied | ||
return normalize(uri); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { NotificationType, RequestType } from 'vscode-languageserver'; | ||
|
||
export namespace SchemaAssociationNotification { | ||
export const type: NotificationType<{ }, { }> = new NotificationType('json/schemaAssociations'); | ||
} | ||
|
||
export namespace DynamicCustomSchemaRequestRegistration { | ||
export const type: NotificationType<{ }, { }> = new NotificationType('yaml/registerCustomSchemaRequest'); | ||
} | ||
|
||
export namespace VSCodeContentRequest { | ||
export const type: RequestType<{ }, { }, { }, { }> = new RequestType('vscode/content'); | ||
} | ||
|
||
export namespace CustomSchemaContentRequest { | ||
export const type: RequestType<{ }, { }, { }, { }> = new RequestType('custom/schema/content'); | ||
} | ||
|
||
export namespace CustomSchemaRequest { | ||
export const type: RequestType<{ }, { }, { }, { }> = new RequestType('custom/schema/request'); | ||
} | ||
|
||
export namespace ColorSymbolRequest { | ||
export const type: RequestType<{ }, { }, { }, { }> = new RequestType('json/colorSymbols'); | ||
} |
Oops, something went wrong.