Skip to content

Commit

Permalink
Merge branch 'refs/heads/develop' into wip/radeusgd/http-tests-retry
Browse files Browse the repository at this point in the history
  • Loading branch information
radeusgd committed Apr 9, 2024
2 parents b425aa9 + 2c78f4e commit 37e5b2d
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,7 @@
- [Implemented `.to_integer`, `.to_float`, and `from` conversions for
`Decimal`][9462]
- [Made `Integer.%` consistent across all `Integer` values.][9589]
- [Added `Decimal.abs`, `.negate` and `.signum`.][9641]

[debug-shortcuts]:
https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug
Expand Down Expand Up @@ -940,6 +941,7 @@
[9525]: https://github.com/enso-org/enso/pull/9525
[9566]: https://github.com/enso-org/enso/pull/9566
[9589]: https://github.com/enso-org/enso/pull/9589
[9641]: https://github.com/enso-org/enso/pull/9641

#### Enso Compiler

Expand Down
14 changes: 13 additions & 1 deletion app/gui2/src/appRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ async function runApp(
_metadata?: object | undefined,
pinia?: Pinia | undefined,
) {
const ignoreParamsRegex = (() => {
if (_metadata)
if ('ignoreParamsRegex' in _metadata)
if (_metadata['ignoreParamsRegex'] instanceof RegExp) return _metadata['ignoreParamsRegex']

return null
})()

running = true
const { mountProjectApp } = await import('./createApp')
if (!running) return
Expand All @@ -19,7 +27,11 @@ async function runApp(
function onUnrecognizedOption(path: string[]) {
unrecognizedOptions.push(path.join('.'))
}
const intermediateConfig = mergeConfig(baseConfig, urlParams(), { onUnrecognizedOption })
const intermediateConfig = mergeConfig(
baseConfig,
urlParams({ ignoreKeysRegExp: ignoreParamsRegex }),
{ onUnrecognizedOption },
)
const appConfig = mergeConfig(intermediateConfig, config ?? {})
unmount = await mountProjectApp({ config: appConfig, accessToken, unrecognizedOptions }, pinia)
}
Expand Down
14 changes: 13 additions & 1 deletion app/gui2/src/util/urlParams.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import type { StringConfig } from './config'

export interface UrlParamsProps {
ignoreKeysRegExp?: RegExp | null
}

/** Returns the parameters passed in the URL query string. */
export function urlParams(): StringConfig {
export function urlParams(props: UrlParamsProps = {}): StringConfig {
const { ignoreKeysRegExp } = props

const params: StringConfig = {}
const urlParams = new URLSearchParams(window.location.search)

for (const [name, value] of urlParams.entries()) {
let obj = params
const path = name.split('.')
const lastSegment = path.pop()

if (ignoreKeysRegExp != null && ignoreKeysRegExp.test(name)) {
continue
}

if (lastSegment == null) {
console.error(`Invalid URL parameter name: '${name}'`)
} else {
Expand Down
10 changes: 10 additions & 0 deletions app/ide-desktop/lib/dashboard/src/appUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
// === Constants ===
// =================

// =============
// === Paths ===
// =============

/** Path to the root of the app (i.e., the Cloud dashboard). */
export const DASHBOARD_PATH = '/'
/** Path to the login page. */
Expand All @@ -28,3 +32,9 @@ export const ALL_PATHS_REGEX = new RegExp(
`${FORGOT_PASSWORD_PATH}|${RESET_PASSWORD_PATH}|${SET_USERNAME_PATH}|` +
`${ENTER_OFFLINE_MODE_PATH}|${SUBSCRIBE_PATH})$`
)

// ===========
// === URL ===
// ===========

export const SEARCH_PARAMS_PREFIX = 'cloud-ide_'
19 changes: 15 additions & 4 deletions app/ide-desktop/lib/dashboard/src/hooks/searchParamsStateHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import * as React from 'react'

import * as reactRouterDom from 'react-router-dom'

import * as appUtils from '#/appUtils'

import * as eventCallback from '#/hooks/eventCallbackHooks'
import * as lazyMemo from '#/hooks/useLazyMemoHooks'

Expand All @@ -32,22 +34,31 @@ export function useSearchParamsState<T = unknown>(
): SearchParamsStateReturnType<T> {
const [searchParams, setSearchParams] = reactRouterDom.useSearchParams()

const prefixedKey = `${appUtils.SEARCH_PARAMS_PREFIX}${key}`

const lazyDefaultValueInitializer = lazyMemo.useLazyMemoHooks(defaultValue, [])
const predicateEventCallback = eventCallback.useEventCallback(predicate)

const clear = eventCallback.useEventCallback((replace: boolean = false) => {
searchParams.delete(key)
searchParams.delete(prefixedKey)
setSearchParams(searchParams, { replace })
})

const unprefixedValue = searchParams.get(key)
if (unprefixedValue != null) {
searchParams.set(prefixedKey, unprefixedValue)
searchParams.delete(key)
setSearchParams(searchParams)
}

const rawValue = React.useMemo<T>(() => {
const maybeValue = searchParams.get(key)
const maybeValue = searchParams.get(prefixedKey)
const defaultValueFrom = lazyDefaultValueInitializer()

return maybeValue != null
? safeJsonParse.safeJsonParse(maybeValue, defaultValueFrom, (unknown): unknown is T => true)
: defaultValueFrom
}, [key, lazyDefaultValueInitializer, searchParams])
}, [prefixedKey, lazyDefaultValueInitializer, searchParams])

const isValueValid = predicateEventCallback(rawValue)

Expand All @@ -71,7 +82,7 @@ export function useSearchParamsState<T = unknown>(
if (nextValue === lazyDefaultValueInitializer()) {
clear()
} else {
searchParams.set(key, JSON.stringify(nextValue))
searchParams.set(prefixedKey, JSON.stringify(nextValue))
setSearchParams(searchParams)
}
})
Expand Down
7 changes: 6 additions & 1 deletion app/ide-desktop/lib/dashboard/src/layouts/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/** @file The container that launches the IDE. */
import * as React from 'react'

import * as appUtils from '#/appUtils'

import * as toastAndLogHooks from '#/hooks/toastAndLogHooks'

import * as backendModule from '#/services/Backend'
Expand Down Expand Up @@ -114,7 +116,10 @@ export default function Editor(props: EditorProps) {
},
},
accessToken,
{ projectId: project.projectId }
{
projectId: project.projectId,
ignoreParamsRegex: new RegExp(`^${appUtils.SEARCH_PARAMS_PREFIX}(.+)$`),
}
)
} catch (error) {
toastAndLog('openEditorError', error)
Expand Down
27 changes: 27 additions & 0 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Decimal.enso
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,33 @@ type Decimal
negate : Decimal
negate self = Decimal.Value self.big_decimal.negate

## GROUP Math
ICON math
Computes the absolute value of this.

The absolute value of a positive number is itself, while the absolute
value of a negative number is that number multiplied by -1.

> Example
Compute the absolute value of a `Decimal`.

Decimal.new "-12.345" . abs
# => 12.345
abs : Decimal
abs self -> Decimal = Decimal.Value self.big_decimal.abs

## GROUP Math
ICON math
Returns the sign of the number.

> Example
Compute the sign of a `Decimal`.

Decimal.new "-12.345" . signum
# => -1
signum : Integer
signum self -> Integer = self.big_decimal.signum

## GROUP CONVERSIONS
Convert this to an `Integer`.

Expand Down
4 changes: 4 additions & 0 deletions distribution/lib/Standard/Base/0.0.0-dev/src/System/File.enso
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,10 @@ type File
ICON metadata
Resolves the parent filesystem node of this file.

The root directory has no parent, so this method will return `Nothing`.
If the file is a relative path, the parent will be resolved relative to
the current working directory.

> Example
Get the parent file of a file.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,15 @@ public Set<PosixFilePermission> getPosixPermissions() throws IOException {
@Builtin.Method(name = "parent")
@CompilerDirectives.TruffleBoundary
public EnsoObject getParent() {
var parentOrNull = this.truffleFile.getParent();
// Normalization is needed to correctly handle paths containing `..` and `.`.
var parentOrNull = this.normalize().truffleFile.getParent();

// If the path has no parent because it is relative and there are no more segments, try again
// after making it absolute:
if (parentOrNull == null && !this.truffleFile.isAbsolute()) {
parentOrNull = this.truffleFile.getAbsoluteFile().normalize().getParent();
}

if (parentOrNull != null) {
return new EnsoFile(parentOrNull);
} else {
Expand Down Expand Up @@ -228,7 +236,7 @@ public boolean isWritable() {
@Builtin.Method(name = "name")
@CompilerDirectives.TruffleBoundary
public Text getName() {
var name = this.truffleFile.getName();
var name = this.normalize().truffleFile.getName();
return Text.create(name == null ? "/" : name);
}

Expand All @@ -255,7 +263,13 @@ public boolean equals(Object obj) {
@Builtin.Method
@CompilerDirectives.TruffleBoundary
public EnsoFile normalize() {
return new EnsoFile(truffleFile.normalize());
TruffleFile simplyNormalized = truffleFile.normalize();
String name = simplyNormalized.getName();
boolean needsAbsolute = name != null && (name.equals("..") || name.equals("."));
if (needsAbsolute) {
simplyNormalized = simplyNormalized.getAbsoluteFile().normalize();
}
return new EnsoFile(simplyNormalized);
}

@Builtin.Method(name = "delete_builtin")
Expand Down
20 changes: 20 additions & 0 deletions test/Base_Tests/src/Data/Decimal_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,26 @@ add_specs suite_builder =
Decimal.new "10" . pow -1 . should_fail_with Arithmetic_Error
Decimal.new "10" . pow 99999999999 . should_fail_with Arithmetic_Error

suite_builder.group "signs" group_builder->
group_builder.specify "should calculate abs correctly" <|
Decimal.new "12.345" . abs . should_equal 12.345
Decimal.new "-12.345" . abs . should_equal 12.345
Decimal.new "12.345E97" . abs . should_equal (Decimal.new "12.345E97")
Decimal.new "-12.345E97" . abs . should_equal (Decimal.new "12.345E97")

group_builder.specify "should calculate negate correctly" <|
Decimal.new "12.345" . negate . should_equal -12.345
Decimal.new "-12.345" . negate . should_equal 12.345
Decimal.new "12.345E97" . negate . should_equal (Decimal.new "-12.345E97")
Decimal.new "-12.345E97" . negate . should_equal (Decimal.new "12.345E97")

group_builder.specify "should calculate signum correctly" <|
Decimal.new "12.345" . signum . should_equal 1
Decimal.new "-12.345" . signum . should_equal -1
Decimal.new "12.345E97" . signum . should_equal 1
Decimal.new "-12.345E97" . signum . should_equal -1
Decimal.new "0" . signum . should_equal 0

main =
suite = Test.build suite_builder->
add_specs suite_builder
Expand Down
45 changes: 42 additions & 3 deletions test/Base_Tests/src/System/File_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,48 @@ add_specs suite_builder =
contents_2 = File.new file . read_bytes
contents_2.take (First 6) . should_equal [67, 117, 112, 99, 97, 107]

group_builder.specify "no parent of dot implies nothing" <|
no_parent = (File.new '.').parent
no_parent.is_nothing . should_be_true
group_builder.specify "should allow going above the first part of a relative directory by resolving it to absolute" <|
parent_file = (File.new '.').parent
parent_file.should_be_a File
parent_file.should_equal (File.new '.' . absolute . normalize . parent)

group_builder.specify "will not resolve a relative directory to absolute in `parent` if not necessary" <|
f = File.new "foo/bar"
f.parent . should_equal (File.new "foo")

group_builder.specify "will return Nothing for a root path that has no parent" <|
root = File.new "/" . absolute . normalize
root.parent . should_equal Nothing

group_builder.specify "will normalize the path when resolving parent to correctly handle . and .." <|
(File.new "a/b/c/././.").parent . should_equal (File.new "a/b")
(File.new "a/b/c/d/e/f/../../..").parent . should_equal (File.new "a/b")
(File.new "a").parent . should_equal (File.new "." . normalize)

(File.new "..").parent . should_equal (File.new "." . parent . parent)
(File.new "./././.").parent . should_equal (File.new "." . parent)

# This may not be necessary but it simplifies the logic a lot:
(File.new "a/b/../././c/d").parent . should_equal (File.new "a/c")

group_builder.specify "correctly handles .. in the path when resolving parent (1)" <|
(File.new "../..").parent . should_not_equal (File.new "..")

up3 = Panic.catch Any (File.new "." . parent . parent . parent) (_->Nothing)
group_builder.specify "correctly handles .. in the path when resolving parent (2)" pending=(if up3.is_nothing then "The current directory does not have enough nesting to run this test (it needs to go up from CWD 3 times).") <|
(File.new "../..").parent . should_equal up3

group_builder.specify "should resolve .. when normalizing" <|
(File.new "a/b/c/../../d").normalize . should_equal (File.new "a/d")
(File.new "..").normalize . should_equal (File.new "." . parent)

group_builder.specify "should return the real file name, not just the last path segment" <|
(File.new "a/b/c/").name . should_equal "c"
(File.new "a/b/c/././.").name . should_equal "c"
(File.new "a/b/c/./../..").name . should_equal "a"

(File.new ".").name . should_equal (File.new "." . absolute . normalize . name)
(File.new "..").name . should_equal (File.new "." . parent . absolute . normalize . name)

suite_builder.group "read_text" group_builder->
group_builder.specify "should allow reading a UTF-8 file" <|
Expand Down

0 comments on commit 37e5b2d

Please sign in to comment.