Skip to content
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

Pu/issue617 #619

Merged
merged 18 commits into from
Apr 14, 2021
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed
- GPU.js constructor needs to be provided directly to engine configuration. (#355)
- An input value should be preserved through serialization more precisely. A **Breaking change**: This changes the type of value returned via serialization. (#617)
- A deprecated config option vlookupThreshold has been removed. (#620)

### Added
Expand Down
5 changes: 1 addition & 4 deletions src/CellContentParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,11 @@ export class CellContentParser {
if (parsedDateNumber !== undefined) {
return new CellContent.Number(parsedDateNumber)
} else {
return new CellContent.String(
content.startsWith('\'') ? content.slice(1) : content,
)
return new CellContent.String(content.startsWith('\'') ? content.slice(1) : content )
}
}
} else {
throw new UnableToParseError(content)
}
}
}

4 changes: 3 additions & 1 deletion src/ClipboardOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import {AbsoluteCellRange} from './AbsoluteCellRange'
import {invalidSimpleCellAddress, simpleCellAddress, SimpleCellAddress} from './Cell'
import {RawCellContent} from './CellContentParser'
import {Operations} from './Operations'
import {DependencyGraph} from './DependencyGraph'
import {ValueCellVertexValue} from './DependencyGraph/ValueCellVertex'
Expand All @@ -30,7 +31,8 @@ export enum ClipboardCellType {

export interface ClipboardCellValue {
type: ClipboardCellType.VALUE,
value: ValueCellVertexValue,
parsedValue: ValueCellVertexValue,
rawValue: RawCellContent,
}

export interface ClipboardCellEmpty {
Expand Down
14 changes: 13 additions & 1 deletion src/DependencyGraph/AddressMapping/AddressMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
*/

import {SimpleCellAddress} from '../../Cell'
import {RawCellContent} from '../../CellContentParser'
import {EmptyValue, InterpreterValue} from '../../interpreter/InterpreterValue'
import {ColumnsSpan, RowsSpan} from '../../Span'
import {MatrixVertex} from '../index'
import {EmptyCellVertex, MatrixVertex, ValueCellVertex} from '../index'
import {CellVertex} from '../Vertex'
import {ChooseAddressMapping} from './ChooseAddressMappingPolicy'
import {IAddressMappingStrategy} from './IAddressMappingStrategy'
Expand Down Expand Up @@ -77,6 +78,17 @@ export class AddressMapping {
}
}

public getRawValue(address: SimpleCellAddress): RawCellContent {
const vertex = this.getCell(address)
if(vertex instanceof ValueCellVertex) {
return vertex.getValues().rawValue
} else if (vertex instanceof MatrixVertex) {
return vertex.getMatrixCellRawValue(address)
} else {
return null
}
}

/** @inheritDoc */
public setCell(address: SimpleCellAddress, newVertex: CellVertex) {
const sheetMapping = this.mapping.get(address.sheet)
Expand Down
21 changes: 13 additions & 8 deletions src/DependencyGraph/DependencyGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
simpleCellAddress,
SimpleCellAddress
} from '../Cell'
import {RawCellContent} from '../CellContentParser'
import {CellDependency} from '../CellDependency'
import {Config} from '../Config'
import {ErrorMessage} from '../error-message'
Expand All @@ -38,7 +39,7 @@ import {Graph, TopSortResult} from './Graph'
import {MatrixMapping} from './MatrixMapping'
import {RangeMapping} from './RangeMapping'
import {SheetMapping} from './SheetMapping'
import {ValueCellVertexValue} from './ValueCellVertex'
import {RawAndParsedValue, ValueCellVertexValue} from './ValueCellVertex'
import {FunctionRegistry} from '../interpreter/FunctionRegistry'
import {
EmptyValue,
Expand Down Expand Up @@ -112,18 +113,18 @@ export class DependencyGraph {
this.correctInfiniteRangesDependency(address)
}

public setValueToCell(address: SimpleCellAddress, newValue: ValueCellVertexValue) {
public setValueToCell(address: SimpleCellAddress, value: RawAndParsedValue) {
const vertex = this.addressMapping.getCell(address)
this.ensureThatVertexIsNonMatrixCellVertex(vertex)

if (vertex instanceof ValueCellVertex) {
const oldValue = vertex.getCellValue()
if (oldValue !== newValue) {
vertex.setCellValue(newValue)
const oldValue = vertex.getValues()
if (oldValue.rawValue !== value.rawValue) {
vertex.setValues(value)
this.graph.markNodeAsSpecialRecentlyChanged(vertex)
}
} else {
const newVertex = new ValueCellVertex(newValue)
const newVertex = new ValueCellVertex(value.parsedValue, value.rawValue)
this.exchangeOrAddGraphNode(vertex, newVertex)
this.addressMapping.setCell(address, newVertex)
this.graph.markNodeAsSpecialRecentlyChanged(newVertex)
Expand Down Expand Up @@ -505,8 +506,8 @@ export class DependencyGraph {
const adjacentNodes = this.graph.adjacentNodes(matrixVertex)

for (const address of matrixRange.addresses(this)) {
const value = this.getCellValue(address) as ExtendedNumber // We wouldn't need that typecast if we would take values from Matrix
const valueVertex = new ValueCellVertex(value)
// We wouldn't need that typecast if we would take values from Matrix
const valueVertex = new ValueCellVertex(this.getCellValue(address) as ExtendedNumber, this.getRawValue(address))
this.addVertex(address, valueVertex)
}

Expand Down Expand Up @@ -605,6 +606,10 @@ export class DependencyGraph {
return this.addressMapping.getCellValue(address)
}

public getRawValue(address: SimpleCellAddress): RawCellContent {
return this.addressMapping.getRawValue(address)
}

public getScalarValue(address: SimpleCellAddress): InternalScalarValue {
const value = this.addressMapping.getCellValue(address)
if (value instanceof SimpleRangeValue) {
Expand Down
5 changes: 5 additions & 0 deletions src/DependencyGraph/MatrixVertex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export class MatrixVertex {
return this.matrix.get(col, row)
}

public getMatrixCellRawValue(address: SimpleCellAddress): number | undefined {
const val = this.getMatrixCellValue(address)
return val instanceof CellError ? undefined : val
}

public setMatrixCellValue(address: SimpleCellAddress, value: number): void {
const col = address.col - this.cellAddress.col
const row = address.row - this.cellAddress.row
Expand Down
29 changes: 19 additions & 10 deletions src/DependencyGraph/ValueCellVertex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,41 @@
*/

import {CellError} from '../Cell'
import {ExtendedNumber} from '../interpreter/InterpreterValue'
import {RawCellContent} from '../CellContentParser'
import {ExtendedNumber, RawScalarValue} from '../interpreter/InterpreterValue'

export type ValueCellVertexValue = ExtendedNumber | boolean | string | CellError

export interface RawAndParsedValue {
parsedValue: ValueCellVertexValue,
rawValue: RawCellContent,
}

/**
* Represents vertex which keeps static cell value
*/
export class ValueCellVertex {
/** Static cell value. */
private cellValue: ValueCellVertexValue
constructor(private parsedValue: ValueCellVertexValue, private rawValue: RawCellContent) {
}

constructor(cellValue: ValueCellVertexValue) {
this.cellValue = cellValue
public getValues(): RawAndParsedValue {
return {parsedValue: this.parsedValue, rawValue: this.rawValue}
}

public setValues(values: RawAndParsedValue) {
this.parsedValue = values.parsedValue
this.rawValue = values.rawValue
}

/**
* Returns cell value stored in vertex
*/
public getCellValue(): ValueCellVertexValue {
return this.cellValue
return this.parsedValue
}

/**
* Sets computed cell value stored in this vertex
*/
public setCellValue(cellValue: ValueCellVertexValue) {
this.cellValue = cellValue
public setCellValue(_cellValue: ValueCellVertexValue): never {
throw 'SetCellValue is deprecated for ValueCellVertex'
}
}
8 changes: 4 additions & 4 deletions src/GraphBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export class SimpleStrategy implements GraphBuilderStrategy {
} else if (parsedCellContent instanceof CellContent.Empty) {
/* we don't care about empty cells here */
} else {
const vertex = new ValueCellVertex(parsedCellContent.value)
const vertex = new ValueCellVertex(parsedCellContent.value, cellContent)
this.columnIndex.add(getRawValue(parsedCellContent.value), address)
this.dependencyGraph.addVertex(address, vertex)
}
Expand Down Expand Up @@ -204,7 +204,7 @@ export class MatrixDetectionStrategy implements GraphBuilderStrategy {
} else if (parsedCellContent instanceof CellContent.Number) {
matrixHeuristic.add(address)
} else {
const vertex = new ValueCellVertex(parsedCellContent.value)
const vertex = new ValueCellVertex(parsedCellContent.value, cellContent)
this.columnSearch.add(parsedCellContent.value, address)
this.dependencyGraph.addVertex(address, vertex)
}
Expand All @@ -219,7 +219,7 @@ export class MatrixDetectionStrategy implements GraphBuilderStrategy {
const elem = notMatrices[i]
for (const address of elem.cells.reverse()) {
const value = sheets[this.dependencyGraph.getSheetName(address.sheet)][address.row][address.col]
const vertex = new ValueCellVertex(Number(value))
const vertex = new ValueCellVertex(Number(value), value)
this.columnSearch.add(Number(value), address)
this.dependencyGraph.addVertex(address, vertex)
}
Expand All @@ -234,7 +234,7 @@ export class MatrixDetectionStrategy implements GraphBuilderStrategy {
export function buildMatrixVertex(ast: ProcedureAst, formulaAddress: SimpleCellAddress): MatrixVertex | ValueCellVertex {
const size = checkMatrixSize(ast, formulaAddress)
if (size instanceof CellError) {
return new ValueCellVertex(size)
return new ValueCellVertex(size, undefined)
}
return new MatrixVertex(formulaAddress, size.width, size.height, ast)
}
8 changes: 4 additions & 4 deletions src/HyperFormula.ts
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ export class HyperFormula implements TypedEmitter {
*
* @category Cells
*/
public getCellSerialized(cellAddress: SimpleCellAddress): NoErrorCellValue {
public getCellSerialized(cellAddress: SimpleCellAddress): RawCellContent {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider this as a breaking change to the public API? IMO yes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

this.ensureEvaluationIsNotSuspended()
return this._serialization.getCellSerialized(cellAddress)
}
Expand Down Expand Up @@ -733,7 +733,7 @@ export class HyperFormula implements TypedEmitter {
*
* @category Sheets
*/
public getSheetSerialized(sheetId: number): NoErrorCellValue[][] {
public getSheetSerialized(sheetId: number): RawCellContent[][] {
this.ensureEvaluationIsNotSuspended()
return this._serialization.getSheetSerialized(sheetId)
}
Expand Down Expand Up @@ -850,7 +850,7 @@ export class HyperFormula implements TypedEmitter {
*
* @category Sheets
*/
public getAllSheetsSerialized(): Record<string, NoErrorCellValue[][]> {
public getAllSheetsSerialized(): Record<string, RawCellContent[][]> {
this.ensureEvaluationIsNotSuspended()
return this._serialization.getAllSheetsSerialized()
}
Expand Down Expand Up @@ -2214,7 +2214,7 @@ export class HyperFormula implements TypedEmitter {
*
* @category Ranges
*/
public getRangeSerialized(leftCorner: SimpleCellAddress, width: number, height: number): CellValue[][] {
public getRangeSerialized(leftCorner: SimpleCellAddress, width: number, height: number): RawCellContent[][] {
const cellRange = AbsoluteCellRange.spanFrom(leftCorner, width, height)
return cellRange.arrayOfAddressesInRange().map(
(subarray) => subarray.map(
Expand Down
22 changes: 11 additions & 11 deletions src/Operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import {EmptyValue, getRawValue} from './interpreter/InterpreterValue'
import {ClipboardCell, ClipboardCellType} from './ClipboardOperations'
import {invalidSimpleCellAddress, simpleCellAddress, SimpleCellAddress} from './Cell'
import {CellError, invalidSimpleCellAddress, simpleCellAddress, SimpleCellAddress} from './Cell'
import {AbsoluteCellRange} from './AbsoluteCellRange'
import {absolutizeDependencies, filterDependenciesOutOfScope} from './absolutizeDependencies'
import {CellContent, CellContentParser, RawCellContent} from './CellContentParser'
Expand All @@ -24,7 +24,7 @@ import {
SparseStrategy,
ValueCellVertex
} from './DependencyGraph'
import {ValueCellVertexValue} from './DependencyGraph/ValueCellVertex'
import {RawAndParsedValue, ValueCellVertexValue} from './DependencyGraph/ValueCellVertex'
import {AddColumnsTransformer} from './dependencyTransformers/AddColumnsTransformer'
import {AddRowsTransformer} from './dependencyTransformers/AddRowsTransformer'
import {MoveCellsTransformer} from './dependencyTransformers/MoveCellsTransformer'
Expand Down Expand Up @@ -444,7 +444,7 @@ export class Operations {
public restoreCell(address: SimpleCellAddress, clipboardCell: ClipboardCell) {
switch (clipboardCell.type) {
case ClipboardCellType.VALUE: {
this.setValueToCell(clipboardCell.value, address)
this.setValueToCell(clipboardCell, address)
break
}
case ClipboardCellType.FORMULA: {
Expand Down Expand Up @@ -577,9 +577,9 @@ export class Operations {
if (vertex === null || vertex instanceof EmptyCellVertex) {
return {type: ClipboardCellType.EMPTY}
} else if (vertex instanceof ValueCellVertex) {
return {type: ClipboardCellType.VALUE, value: vertex.getCellValue()}
return {type: ClipboardCellType.VALUE, ...vertex.getValues()}
} else if (vertex instanceof MatrixVertex) {
return {type: ClipboardCellType.VALUE, value: vertex.getMatrixCellValue(address)}
return {type: ClipboardCellType.VALUE, parsedValue: vertex.getMatrixCellValue(address), rawValue: vertex.getMatrixCellRawValue(address)}
} else if (vertex instanceof FormulaCellVertex) {
return {
type: ClipboardCellType.FORMULA,
Expand Down Expand Up @@ -659,7 +659,7 @@ export class Operations {
} else if (parsedCellContent instanceof CellContent.MatrixFormula) {
throw new Error('Cant happen')
} else {
this.setValueToCell(parsedCellContent.value, address)
this.setValueToCell({parsedValue: parsedCellContent.value, rawValue: newCellContent}, address)
}
} else {
throw new Error('Illegal operation')
Expand All @@ -676,11 +676,11 @@ export class Operations {
}
}

public setValueToCell(value: ValueCellVertexValue, address: SimpleCellAddress) {
public setValueToCell(value: RawAndParsedValue, address: SimpleCellAddress) {
const oldValue = this.dependencyGraph.getCellValue(address)
this.dependencyGraph.setValueToCell(address, value)
this.columnSearch.change(getRawValue(oldValue), getRawValue(value), address)
this.changes.addChange(value, address)
this.columnSearch.change(getRawValue(oldValue), getRawValue(value.parsedValue), address)
this.changes.addChange(value.parsedValue, address)
}

public setCellEmpty(address: SimpleCellAddress) {
Expand Down Expand Up @@ -776,7 +776,7 @@ export class Operations {
if (parsedCellContent instanceof CellContent.Empty) {
this.setCellEmpty(address)
} else {
this.setValueToCell(parsedCellContent.value, address)
this.setValueToCell({parsedValue: parsedCellContent.value, rawValue: expression}, address)
}
}
}
Expand Down Expand Up @@ -847,7 +847,7 @@ export class Operations {
} else if (sourceVertex instanceof EmptyCellVertex) {
this.setCellEmpty(expression.address)
} else if (sourceVertex instanceof ValueCellVertex) {
this.setValueToCell(sourceVertex.getCellValue(), expression.address)
this.setValueToCell(sourceVertex.getValues(), expression.address)
}
}
return this.dependencyGraph.fetchCellOrCreateEmpty(expression.address)
Expand Down
Loading