mirror of
https://github.com/enso-org/enso.git
synced 2024-12-21 14:01:34 +03:00
cbf6d41e4c
This is a prerequisite for adding a CI action for E2E tests. - Fix E2E tests - Remove visual regression testing (VRT) and associated fixtures (screenshots) for now - Switch dashboard almost fully to Vite, from ESBuild, to match GUI2's build tooling. - Add some new E2E tests: - Creating assets - Deleting assets - Creating assets from the samples on the home page - Sort assets - Includes fixes for sorting: - Group sorted assets by type again (regression) (see https://github.com/enso-org/cloud-v2/issues/554) - Make sorting by title, case insensitive. This is because it is more intuitive for non-programmers if all items with uppercase names *aren't* separated from those with lowercase names - especially since the Windows FS is case-insensitive. - Normalization of Unicode letters is *not* currently being done. It can potentially be added later. - Double-clicking *anywhere* on a directory row now expands it. Previously it was only being expanded when double clicking - Add recursive label adding/removal to mirror backend - Note: The current implementation is not exactly the same as the backend's implementation. - Fix https://github.com/enso-org/cloud-v2/issues/872 - Unset "saved project details" (for opening the last open project) if fetching it produces an error. # Important Notes - All tests pass. (run `npm run test:e2e` in `app/ide-desktop/lib/dashboard`) - All `npm` commands should be run in `app/ide-desktop/lib/dashboard`. `dashboard:*` npm scripts have been removed from `app/ide-desktop` to prevent a mess. - `npm run dev` confirmed to still work. Note that it has not been changed as it was already using Vite. - `npm run build` now uses `vite build`. This has been tested using a local HTTP server that supports `404.html`. - Other cases have been tested: - `npm run test:e2e` works (all tests pass) - `./run ide build` works - `./run ide watch` works - `./run ide2 build` works - `./run gui watch` works
160 lines
5.3 KiB
JavaScript
160 lines
5.3 KiB
JavaScript
/** @file A plugin to change auto-imports to use `import * as module` instead of `import {}`. */
|
|
|
|
/** A TypeScript compiler plugin. */
|
|
module.exports = function init() {
|
|
/** Turn a module name into a valid identifier.
|
|
* @param {string} name - module name */
|
|
const normalizeModuleName = name => {
|
|
const intermediate = name.length === 0 ? '' : name[0].toLowerCase() + name.slice(1)
|
|
const result = intermediate.replace(/^\W+|\W+(.?)/g, (_, a) =>
|
|
String(a ?? '').toUpperCase()
|
|
)
|
|
return NON_CONTEXTUAL_KEYWORDS.has(result) ? '_' + result : result
|
|
}
|
|
|
|
/** Create the plugin.
|
|
* @param {import('typescript/lib/tsserverlibrary').server.PluginCreateInfo} info - Plugin utilities. */
|
|
const create = info => {
|
|
/** @type {import('typescript/lib/tsserverlibrary').LanguageService} */
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
const proxy = Object.create(null)
|
|
const oldLS = info.languageService
|
|
for (const [k, v] of Object.entries(oldLS)) {
|
|
// @ts-expect-error Runtime reflection is not type-safe.
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
proxy[k] = (...args) => v.apply(oldLS, args)
|
|
}
|
|
|
|
proxy.getCompletionsAtPosition = (fileName, position, options) => {
|
|
const result = info.languageService.getCompletionsAtPosition(
|
|
fileName,
|
|
position,
|
|
options
|
|
)
|
|
for (const completion of result?.entries ?? []) {
|
|
if (
|
|
completion.hasAction &&
|
|
/\bexport\b/.test(completion.kindModifiers ?? '') &&
|
|
completion.data?.exportName !== 'default'
|
|
) {
|
|
const moduleName = completion.data?.moduleSpecifier?.match(/[^/]+$/)?.[0] ?? ''
|
|
if (moduleName) {
|
|
completion.insertText = `${normalizeModuleName(moduleName)}.${
|
|
completion.name
|
|
}`
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
proxy.getCompletionEntryDetails = (
|
|
fileName,
|
|
position,
|
|
entryName,
|
|
formatOptions,
|
|
source,
|
|
preferences,
|
|
data
|
|
) => {
|
|
const result = info.languageService.getCompletionEntryDetails(
|
|
fileName,
|
|
position,
|
|
entryName,
|
|
formatOptions,
|
|
source,
|
|
preferences,
|
|
data
|
|
)
|
|
for (const action of result?.codeActions ?? []) {
|
|
if (action.description.startsWith('Add import from ')) {
|
|
for (const change of action.changes) {
|
|
for (const textChange of change.textChanges) {
|
|
textChange.newText = textChange.newText.replace(
|
|
/^(import ){.*}( from (['"])(?:.*[/])?(.*)\3)/m,
|
|
(_, prefix, suffix, _quote, moduleName) =>
|
|
`${prefix}* as ${normalizeModuleName(
|
|
String(moduleName)
|
|
)}${suffix}`
|
|
)
|
|
}
|
|
}
|
|
} else if (action.description.startsWith('Update import from ')) {
|
|
const moduleName =
|
|
action.description.match(/(['"])(?:.*[/])?(?<moduleName>.*)\1/)?.groups
|
|
?.moduleName ?? ''
|
|
const replacement = `, * as ${normalizeModuleName(moduleName)}`
|
|
for (const change of action.changes) {
|
|
for (const textChange of change.textChanges) {
|
|
textChange.newText = textChange.newText.replace(
|
|
/^, {.*}$/m,
|
|
replacement
|
|
)
|
|
}
|
|
}
|
|
// "Change 'foo' to 'module.foo'"
|
|
} else if (/^Change '(.*)' to '.*[.]\1'$/.test(action.description)) {
|
|
for (const change of action.changes) {
|
|
for (const textChange of change.textChanges) {
|
|
textChange.newText = ''
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
return proxy
|
|
}
|
|
|
|
return { create }
|
|
}
|
|
|
|
const NON_CONTEXTUAL_KEYWORDS = new Set([
|
|
'break',
|
|
'case',
|
|
'catch',
|
|
'class',
|
|
'const',
|
|
'continue',
|
|
'debugger',
|
|
'default',
|
|
'delete',
|
|
'do',
|
|
'else',
|
|
'enum',
|
|
'export',
|
|
'extends',
|
|
'false',
|
|
'finally',
|
|
'for',
|
|
'function',
|
|
'if',
|
|
'import',
|
|
'in',
|
|
'instanceof',
|
|
'new',
|
|
'null',
|
|
'return',
|
|
'super',
|
|
'switch',
|
|
'this',
|
|
'throw',
|
|
'true',
|
|
'try',
|
|
'typeof',
|
|
'var',
|
|
'void',
|
|
'while',
|
|
'with',
|
|
'implements',
|
|
'interface',
|
|
'let',
|
|
'package',
|
|
'private',
|
|
'protected',
|
|
'public',
|
|
'static',
|
|
'yield',
|
|
])
|