Skip to content

Commit

Permalink
Merge Sequence Editors Time library (#1339)
Browse files Browse the repository at this point in the history
* Revert typescript to 5.0.4
This was causing the custom worker to incorrectly label the tree nodes and break the custom checks.

* Update time library
* Add sequence related utilities function to the library
* Added more time unit test

* Autocomplete with valid times

* Update seqN linter to use the Time.ts

* Export seqJson uses Time.ts

* Updated the eDSL to use Time.ts

* Bug fix for 'time quick fix' action in Monaco

* Remove old sequence time library

* linter fix

* specify the return object of `parseDoyOrYmdTime`
  • Loading branch information
goetzrrGit authored Jun 25, 2024
1 parent 92e2736 commit 850ed62
Show file tree
Hide file tree
Showing 17 changed files with 787 additions and 659 deletions.
10 changes: 5 additions & 5 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
"stylelint-order": "^6.0.4",
"svelte-check": "^3.4.4",
"tslib": "^2.6.0",
"typescript": "5.4.3",
"typescript": "5.0.4",
"unique-names-generator": "^4.7.1",
"vite": "5.1.6",
"vitest": "^1.0.0"
Expand Down
7 changes: 3 additions & 4 deletions src/components/model/ModelForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@
let owner: UserId | null = null;
let version: string = '';
let description: string = '';
let modelLogs: Pick<
ModelSlim,
'refresh_activity_type_logs' | 'refresh_model_parameter_logs' | 'refresh_resource_type_logs'
> | null = null;
let modelLogs:
| Pick<ModelSlim, 'refresh_activity_type_logs' | 'refresh_model_parameter_logs' | 'refresh_resource_type_logs'>
| undefined = undefined;
$: description = initialModelDescription;
$: name = initialModelName;
Expand Down
2 changes: 1 addition & 1 deletion src/components/sequencing/form/SelectedCommand.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@
}
}
function hasAncestorWithId(element: Element | null, id: string) {
function hasAncestorWithId(element: Element | null, id: string): boolean {
if (element === null) {
return false;
} else if (element.id === id) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/DatePicker/DatePicker.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
* Converts a date string (YYYY-MM-DDTHH:mm:ss) or DOY string (YYYY-DDDDTHH:mm:ss) into a Date object
*/
function getDateFromString(dateString: string): Date | null {
const parsedDate = parseDoyOrYmdTime(dateString);
const parsedDate = parseDoyOrYmdTime(dateString) as ParsedYmdString | ParsedDoyString;
if (parsedDate !== null) {
const { hour, min, ms, sec, year } = parsedDate;
Expand Down
7 changes: 7 additions & 0 deletions src/enums/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ export enum TIME_MS {
MONTH = 2629800000,
YEAR = 31557600000,
}
export enum TimeTypes {
ABSOLUTE = 'absolute',
EPOCH = 'epoch',
EPOCH_SIMPLE = 'epoch_simple',
RELATIVE = 'relative',
RELATIVE_SIMPLE = 'relative_simple',
}
10 changes: 10 additions & 0 deletions src/types/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ export type ParsedDurationString = {
seconds: number;
years: number;
};
export type DurationTimeComponents = {
days: string;
hours: string;
isNegative: string;
microseconds: string;
milliseconds: string;
minutes: string;
seconds: string;
years: string;
};

export type ParsedYmdString = {
day: number;
Expand Down
9 changes: 7 additions & 2 deletions src/utilities/monacoHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const sequenceProvideCodeActions = (
.map(unbalancedTime => {
const match = unbalancedTime.message.match(/Suggestion:\s*(.*)/);
if (match) {
const extractSuggestedTime = match[1].replace(/\s+/g, '');
const extractSuggestedTime = match[1].replace(/\s+|[\\[|\]]/g, '');
return generateQuickFixAction('Convert Unbalanced Time', extractSuggestedTime, unbalancedTime, model);
}
return undefined; // Return undefined when the match fails
Expand Down Expand Up @@ -42,7 +42,12 @@ function generateQuickFixAction(
{
resource: model.uri,
textEdit: {
range: diagnostics,
range: {
endColumn: diagnostics.endColumn - 1,
endLineNumber: diagnostics.endLineNumber,
startColumn: diagnostics.startColumn + 2,
startLineNumber: diagnostics.startLineNumber,
},
text: replaceText,
},
versionId: model.getVersionId(),
Expand Down
13 changes: 11 additions & 2 deletions src/utilities/new-sequence-editor/sequence-completion.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import { syntaxTree } from '@codemirror/language';
import type { ChannelDictionary, CommandDictionary, ParameterDictionary } from '@nasa-jpl/aerie-ampcs';
import { getDoyTime } from '../time';
import { fswCommandArgDefault } from './command-dictionary';
import { getCustomArgDef } from './extension-points';

Expand Down Expand Up @@ -103,9 +104,17 @@ export function sequenceCompletion(
);

if (!cursor.isTimeTagBefore) {
//get the first of the year date
const date = new Date();
date.setMonth(0);
date.setDate(1);
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
timeTagCompletions.push(
{
apply: 'A0000-000T00:00:00 ',
apply: `A${getDoyTime(date)} `,
info: 'Execute command at an absolute time',
label: `A (absolute)`,
section: 'Time Tags',
Expand All @@ -119,7 +128,7 @@ export function sequenceCompletion(
type: 'keyword',
},
{
apply: 'E+00:00:00 ',
apply: 'E1 ',
info: 'Execute command at an offset from an epoch',
label: 'E (epoch)',
section: 'Time Tags',
Expand Down
116 changes: 60 additions & 56 deletions src/utilities/new-sequence-editor/sequence-linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,20 @@ import { closest, distance } from 'fastest-levenshtein';

import type { VariableDeclaration } from '@nasa-jpl/seq-json-schema/types';
import type { EditorView } from 'codemirror';
import { TimeTypes } from '../../enums/time';
import { CustomErrorCodes } from '../../workers/customCodes';
import { addDefaultArgs, quoteEscape } from '../codemirror/codemirror-utils';
import { getCustomArgDef } from './extension-points';
import { TOKEN_COMMAND, TOKEN_ERROR, TOKEN_REPEAT_ARG } from './sequencer-grammar-constants';
import {
ABSOLUTE_TIME,
EPOCH_SIMPLE,
EPOCH_TIME,
RELATIVE_SIMPLE,
RELATIVE_TIME,
getBalancedDuration,
getDoyTime,
getUnixEpochTime,
isTimeBalanced,
testTime,
} from './time-utils';
isTimeMax,
parseDurationString,
validateTime,
} from '../time';
import { getCustomArgDef } from './extension-points';
import { TOKEN_COMMAND, TOKEN_ERROR, TOKEN_REPEAT_ARG } from './sequencer-grammar-constants';
import { getChildrenNode, getDeepestNode, getFromAndTo } from './tree-utils';

const KNOWN_DIRECTIVES = [
Expand Down Expand Up @@ -481,101 +483,103 @@ export function sequenceLinter(
if (timeTagAbsoluteNode) {
const absoluteText = text.slice(timeTagAbsoluteNode.from + 1, timeTagAbsoluteNode.to).trim();

if (!testTime(absoluteText, ABSOLUTE_TIME)) {
const isValid = validateTime(absoluteText, TimeTypes.ABSOLUTE);
if (!isValid) {
diagnostics.push({
actions: [],
from: timeTagAbsoluteNode.from,
message: `Time Error: Incorrectly formatted 'Absolute' time.
Received : Malformed Absolute time.
Expected: YYYY-DOYThh:mm:ss[.sss]`,
message: CustomErrorCodes.InvalidAbsoluteTime().message,
severity: 'error',
to: timeTagAbsoluteNode.to,
});
} else {
const result = isTimeBalanced(absoluteText, ABSOLUTE_TIME);
if (result.error) {
if (isTimeMax(absoluteText, TimeTypes.ABSOLUTE)) {
diagnostics.push({
actions: [],
from: timeTagAbsoluteNode.from,
message: result.error,
message: CustomErrorCodes.MaxAbsoluteTime().message,
severity: 'error',
to: timeTagAbsoluteNode.to,
});
} else if (result.warning) {
diagnostics.push({
actions: [],
from: timeTagAbsoluteNode.from,
message: result.warning,
severity: 'warning',
to: timeTagAbsoluteNode.to,
});
} else {
if (!isTimeBalanced(absoluteText, TimeTypes.ABSOLUTE)) {
diagnostics.push({
actions: [],
from: timeTagAbsoluteNode.from,
message: CustomErrorCodes.UnbalancedTime(getDoyTime(new Date(getUnixEpochTime(absoluteText))))
.message,
severity: 'warning',
to: timeTagAbsoluteNode.to,
});
}
}
}
} else if (timeTagEpochNode) {
const epochText = text.slice(timeTagEpochNode.from + 1, timeTagEpochNode.to).trim();
if (!testTime(epochText, EPOCH_TIME) && !testTime(epochText, EPOCH_SIMPLE)) {
const isValid = validateTime(epochText, TimeTypes.EPOCH) || validateTime(epochText, TimeTypes.EPOCH_SIMPLE);
if (!isValid) {
diagnostics.push({
actions: [],
from: timeTagEpochNode.from,
message: `Time Error: Incorrectly formatted 'Epoch' time.
Received : Malformed Epoch time.
Expected: YYYY-DOYThh:mm:ss[.sss] or [+/-]ss`,
message: CustomErrorCodes.InvalidEpochTime().message,
severity: 'error',
to: timeTagEpochNode.to,
});
} else {
if (testTime(epochText, EPOCH_TIME)) {
const result = isTimeBalanced(epochText, EPOCH_TIME);
if (result.error) {
if (validateTime(epochText, TimeTypes.EPOCH)) {
if (isTimeMax(epochText, TimeTypes.EPOCH)) {
diagnostics.push({
actions: [],
from: timeTagEpochNode.from,
message: result.error,
message: CustomErrorCodes.MaxEpochTime(parseDurationString(epochText, 'seconds').isNegative).message,
severity: 'error',
to: timeTagEpochNode.to,
});
} else if (result.warning) {
diagnostics.push({
actions: [],
from: timeTagEpochNode.from,
message: result.warning,
severity: 'warning',
to: timeTagEpochNode.to,
});
} else {
if (!isTimeBalanced(epochText, TimeTypes.EPOCH)) {
diagnostics.push({
actions: [],
from: timeTagEpochNode.from,
message: CustomErrorCodes.UnbalancedTime(getBalancedDuration(epochText)).message,
severity: 'warning',
to: timeTagEpochNode.to,
});
}
}
}
}
} else if (timeTagRelativeNode) {
const relativeText = text.slice(timeTagRelativeNode.from + 1, timeTagRelativeNode.to).trim();
if (!testTime(relativeText, RELATIVE_TIME) && !testTime(relativeText, RELATIVE_SIMPLE)) {
const isValid =
validateTime(relativeText, TimeTypes.RELATIVE) || validateTime(relativeText, TimeTypes.RELATIVE_SIMPLE);
if (!isValid) {
diagnostics.push({
actions: [],
from: timeTagRelativeNode.from,
message: `Time Error: Incorrectly formatted 'Relative' time.
Received : Malformed Relative time.
Expected: [+/-]hh:mm:ss[.sss]`,
message: CustomErrorCodes.InvalidRelativeTime().message,
severity: 'error',
to: timeTagRelativeNode.to,
});
} else {
if (testTime(relativeText, RELATIVE_TIME)) {
const result = isTimeBalanced(relativeText, RELATIVE_TIME);
if (result.error) {
if (validateTime(relativeText, TimeTypes.RELATIVE)) {
if (isTimeMax(relativeText, TimeTypes.RELATIVE)) {
diagnostics.push({
actions: [],
from: timeTagRelativeNode.from,
message: result.error,
message: CustomErrorCodes.MaxRelativeTime().message,
severity: 'error',
to: timeTagRelativeNode.to,
});
} else if (result.warning) {
diagnostics.push({
actions: [],
from: timeTagRelativeNode.from,
message: result.warning,
severity: 'warning',
to: timeTagRelativeNode.to,
});
} else {
if (!isTimeBalanced(relativeText, TimeTypes.EPOCH)) {
diagnostics.push({
actions: [],
from: timeTagRelativeNode.from,
message: CustomErrorCodes.UnbalancedTime(getBalancedDuration(relativeText)).message,
severity: 'error',
to: timeTagRelativeNode.to,
});
}
}
}
}
Expand Down
Loading

0 comments on commit 850ed62

Please sign in to comment.