Skip to content

Add rescript.settings.platformPath and correctly determine its default value #573

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 6 commits into from
Sep 23, 2022
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
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,15 @@ Even if the pre-release channel seems too experimental to you, we still suggest

You'll find all ReScript specific settings under the scope `rescript.settings`.

| Setting | Description |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Prompt to Start Build | If there's no ReScript build running already in the opened project, the extension will prompt you and ask if you want to start a build automatically. You can turn off this automatic prompt via the setting `rescript.settings.askToStartBuild`. |
| ReScript Binary Path | The extension will look for the existence of a `/node_modules/.bin/rescript` file and use its directory as the `binaryPath`. If it does not find it at the project root (which is where the nearest `bsconfig.json` resides), it goes up folders in the filesystem recursively until it either finds it (often the case in monorepos) or hits the top level. To override this lookup process, the path can be configured explicitly using the setting `rescript.settings.binaryPath` |
| Inlay Hints (experimental) | This allows an editor to place annotations inline with text to display type hints. Enable using `rescript.settings.inlayHints.enable: true` |
| Code Lens (experimental) | This tells the editor to add code lenses to function definitions, showing its full type above the definition. Enable using `rescript.settings.codeLens: true` |
| Signature Help (experimental) | This tells the editor to show signature help when you're writing function calls. Enable using `rescript.settings.signatureHelp.enable: true` |
| Autostarting the Code Analyzer | The Code Analyzer needs to be started manually by default. However, you can configure the extension to start the Code Analyzer automatically via the setting `rescript.settings.autoRunCodeAnalysis`. |
| Setting | Description |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Prompt to Start Build | If there's no ReScript build running already in the opened project, the extension will prompt you and ask if you want to start a build automatically. You can turn off this automatic prompt via the setting `rescript.settings.askToStartBuild`. |
| ReScript Binary Path | The extension will look for the existence of a `node_modules/.bin/rescript` file and use its directory as the `binaryPath`. If it does not find it at the project root (which is where the nearest `bsconfig.json` resides), it goes up folders in the filesystem recursively until it either finds it (often the case in monorepos) or hits the top level. To override this lookup process, the path can be configured explicitly using the setting `rescript.settings.binaryPath` |
| ReScript Platform Path | The extension will look for the existence of a `node_modules/rescript` directory and use the subdirectory corresponding to the current platform as the `platformPath`. If it does not find it at the project root (which is where the nearest `bsconfig.json` resides), it goes up folders in the filesystem recursively until it either finds it (often the case in monorepos) or hits the top level. To override this lookup process, the path can be configured explicitly using the setting `rescript.settings.platformPath` |
| Inlay Hints (experimental) | This allows an editor to place annotations inline with text to display type hints. Enable using `rescript.settings.inlayHints.enable: true` |
| Code Lens (experimental) | This tells the editor to add code lenses to function definitions, showing its full type above the definition. Enable using `rescript.settings.codeLens: true` |
| Signature Help (experimental) | This tells the editor to show signature help when you're writing function calls. Enable using `rescript.settings.signatureHelp.enable: true` |
| Autostarting the Code Analyzer | The Code Analyzer needs to be started manually by default. However, you can configure the extension to start the Code Analyzer automatically via the setting `rescript.settings.autoRunCodeAnalysis`. |

**Default settings:**

Expand All @@ -122,9 +123,12 @@ You'll find all ReScript specific settings under the scope `rescript.settings`.
// Automatically start ReScript's code analysis.
"rescript.settings.autoRunCodeAnalysis": false,

// Path to the directory where ReScript binaries are. You can use it if you haven't or don't want to use the installed ReScript from node_modules in your project.
// Path to the directory where cross-platform ReScript binaries are. You can use it if you haven't or don't want to use the installed ReScript from node_modules in your project.
"rescript.settings.binaryPath": null

// Path to the directory where platform-specific ReScript binaries are. You can use it if you haven't or don't want to use the installed ReScript from node_modules in your project.
"rescript.settings.platformPath": null

// Enable (experimental) inlay hints.
"rescript.settings.inlayHints.enable": true

Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,12 @@
"rescript.settings.binaryPath": {
"type": ["string", "null"],
"default": null,
"description": "Path to the directory where ReScript binaries are. You can use it if you haven't or don't want to use the installed ReScript from node_modules in your project."
"description": "Path to the directory where cross-platform ReScript binaries are. You can use it if you haven't or don't want to use the installed ReScript from node_modules in your project."
},
"rescript.settings.platformPath": {
"type": ["string", "null"],
"default": null,
"description": "Path to the directory where platform-specific ReScript binaries are. You can use it if you haven't or don't want to use the installed ReScript from node_modules in your project."
}
}
},
Expand Down
75 changes: 27 additions & 48 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ interface extensionConfiguration {
};
codeLens: boolean;
binaryPath: string | null;
platformPath: string | null;
signatureHelp: {
enable: boolean;
};
Expand All @@ -58,6 +59,7 @@ let extensionConfiguration: extensionConfiguration = {
},
codeLens: false,
binaryPath: null,
platformPath: null,
signatureHelp: {
enable: false,
},
Expand Down Expand Up @@ -98,60 +100,37 @@ let codeActionsFromDiagnostics: codeActions.filesCodeActions = {};
// will be properly defined later depending on the mode (stdio/node-rpc)
let send: (msg: p.Message) => void = (_) => {};

// Check if the rescript binary is available at node_modules/.bin/rescript,
// otherwise recursively check parent directories for it.
let findBinaryPathFromProjectRoot = (
directory: p.DocumentUri // This must be a directory and not a file!
): null | p.DocumentUri => {
let binaryDirPath = path.join(directory, c.nodeModulesBinDir);
let binaryPath = path.join(binaryDirPath, c.rescriptBinName);
let findRescriptBinary = (projectRootPath: p.DocumentUri | null) =>
extensionConfiguration.binaryPath == null
? utils.findFilePathFromProjectRoot(projectRootPath, path.join(c.nodeModulesBinDir, c.rescriptBinName))
: utils.findBinary(extensionConfiguration.binaryPath, c.rescriptBinName);

if (fs.existsSync(binaryPath)) {
return binaryPath;
let findPlatformPath = (projectRootPath: p.DocumentUri | null) => {
if (extensionConfiguration.platformPath != null) {
return extensionConfiguration.platformPath;
}

let parentDir = path.dirname(directory);
if (parentDir === directory) {
// reached the top
let rescriptDir = utils.findFilePathFromProjectRoot(projectRootPath, path.join("node_modules", "rescript"));
if (rescriptDir == null) {
return null;
}

return findBinaryPathFromProjectRoot(parentDir);
};

let findRescriptBinary = (projectRootPath: p.DocumentUri) =>
extensionConfiguration.binaryPath == null
? findBinaryPathFromProjectRoot(projectRootPath)
: utils.findRescriptBinary(extensionConfiguration.binaryPath);

let findBscBinary = (projectRootPath: p.DocumentUri) => {
let rescriptBinaryPath = findRescriptBinary(projectRootPath);
if (rescriptBinaryPath !== null) {
let rescriptDirPath = path.join(
path.dirname(rescriptBinaryPath),
"..",
"rescript"
);
let platformPath = path.join(rescriptDir, c.platformDir)

let bscBinaryPath = path.join(rescriptDirPath, c.platformDir, c.bscExeName);
// Workaround for darwinarm64 which has no folder yet in ReScript <= 9.1.4
if (
process.platform == "darwin" &&
process.arch == "arm64" &&
!fs.existsSync(platformPath)
) {
platformPath = path.join(rescriptDir, process.platform);
}

// Workaround for darwinarm64 which has no folder yet in ReScript <= 9.1.4
if (
process.platform == "darwin" &&
process.arch == "arm64" &&
!fs.existsSync(bscBinaryPath)
) {
bscBinaryPath = path.join(
rescriptDirPath,
process.platform,
c.bscExeName
);
}
return platformPath;
}

return bscBinaryPath;
}
return null;
};
let findBscExeBinary = (projectRootPath: p.DocumentUri | null) =>
utils.findBinary(findPlatformPath(projectRootPath), c.bscExeName)

interface CreateInterfaceRequestParams {
uri: string;
Expand Down Expand Up @@ -786,12 +765,12 @@ function format(msg: p.RequestMessage): Array<p.Message> {
} else {
// code will always be defined here, even though technically it can be undefined
let code = getOpenedFileContent(params.textDocument.uri);

let projectRootPath = utils.findProjectRootOfFile(filePath);
let bscBinaryPath =
projectRootPath === null ? null : findBscBinary(projectRootPath);
let bscExeBinaryPath = findBscExeBinary(projectRootPath);

let formattedResult = utils.formatCode(
bscBinaryPath,
bscExeBinaryPath,
filePath,
code,
extensionConfiguration.allowBuiltInFormatter
Expand Down
37 changes: 25 additions & 12 deletions server/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,31 @@ export let findProjectRootOfFile = (
}
};

// Check if filePartialPath exists at directory and return the joined path,
// otherwise recursively check parent directories for it.
export let findFilePathFromProjectRoot = (
directory: p.DocumentUri | null, // This must be a directory and not a file!
filePartialPath: string
): null | p.DocumentUri => {
if (directory == null) {
return null;
}

let filePath: p.DocumentUri = path.join(directory, filePartialPath);
if (fs.existsSync(filePath)) {
return filePath;
}

let parentDir: p.DocumentUri = path.dirname(directory);
if (parentDir === directory) {
// reached the top
return null;
}

return findFilePathFromProjectRoot(parentDir, filePartialPath);
};

// Check if binaryName exists inside binaryDirPath and return the joined path.
export let findBinary = (
binaryDirPath: p.DocumentUri | null,
binaryName: string
Expand All @@ -53,18 +78,6 @@ export let findBinary = (
}
};

export let findRescriptBinary = (
binaryDirPath: p.DocumentUri | null
): p.DocumentUri | null => {
return findBinary(binaryDirPath, c.rescriptBinName);
};

export let findBscBinary = (
binaryDirPath: p.DocumentUri | null
): p.DocumentUri | null => {
return findBinary(binaryDirPath, c.bscBinName);
};

type execResult =
| {
kind: "success";
Expand Down