Skip to content

Commit cabd495

Browse files
committedJul 31, 2020
feat: Basic runtime data generation with optimizer disabled.
1 parent a825a16 commit cabd495

File tree

9 files changed

+369
-32
lines changed

9 files changed

+369
-32
lines changed
 

‎packages/@css-blocks/core/src/Analyzer/Analysis.ts

+1
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ export class Analysis<K extends keyof TemplateTypes> {
469469
}
470470
element.seal();
471471
analysis.elements.set(elID, element);
472+
if(analysis.onElementAnalyzed) analysis.onElementAnalyzed(element);
472473
});
473474

474475
return analysis;

‎packages/@css-blocks/core/src/Analyzer/Analyzer.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export abstract class Analyzer<K extends keyof TemplateTypes> {
3333
protected analysisMap: Map<string, Analysis<K>>;
3434
protected staticStyles: MultiMap<Style, Analysis<K>>;
3535
protected dynamicStyles: MultiMap<Style, Analysis<K>>;
36+
public stylesFound: Set<Style>;
3637

3738
constructor (
3839
blockFactory: BlockFactory,
@@ -49,6 +50,7 @@ export abstract class Analyzer<K extends keyof TemplateTypes> {
4950
this.analysisMap = new Map();
5051
this.staticStyles = new MultiMap();
5152
this.dynamicStyles = new MultiMap();
53+
this.stylesFound = new Set();
5254
}
5355

5456
abstract analyze(dir: string, entryPoints: string[]): Promise<Analyzer<K>>;
@@ -61,11 +63,15 @@ export abstract class Analyzer<K extends keyof TemplateTypes> {
6163
this.analysisMap = new Map();
6264
this.staticStyles = new MultiMap();
6365
this.dynamicStyles = new MultiMap();
66+
this.stylesFound = new Set();
6467
this.blockFactory.reset();
6568
}
6669

6770
newAnalysis(info: TemplateTypes[K]): Analysis<K> {
6871
let analysis = new Analysis<K>(info, this.validatorOptions, (element) => {
72+
for (let s of element.stylesFound()) {
73+
this.stylesFound.add(s);
74+
}
6975
for (let s of [...element.classesFound(false), ...element.attributesFound(false)]) {
7076
this.staticStyles.set(s, analysis);
7177
}
@@ -89,7 +95,7 @@ export abstract class Analyzer<K extends keyof TemplateTypes> {
8995
return analyses;
9096
}
9197

92-
styleCount(): number { return this.staticStyles.size; }
98+
staticCount(): number { return this.staticStyles.size; }
9399

94100
dynamicCount(): number { return this.dynamicStyles.size; }
95101

‎packages/@css-blocks/core/src/BlockTree/Block.ts

+49-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { MultiMap, ObjectDictionary } from "@opticss/util";
1+
import { MultiMap, ObjectDictionary, unionInto } from "@opticss/util";
22
import {
33
CompoundSelector,
44
ParsedSelector,
@@ -84,6 +84,7 @@ export class Block
8484
*/
8585
public precompiledStylesheet: postcss.Root | undefined;
8686
public blockReferencePaths: Map<string, Block>;
87+
private _resolveImplementedBlocksResult: Set<Block> | undefined;
8788

8889
/**
8990
* Creates a new Block.
@@ -448,6 +449,24 @@ export class Block
448449
return result;
449450
}
450451

452+
/**
453+
* Outputs a dictionary of style source string to most specific style in the
454+
* inheritance hierarchy.
455+
*/
456+
resolvedStyleInterface(): ObjectDictionary<Styles> {
457+
// starting with the base block and working up to the most specific sub-block
458+
// we record the most specific style associated with the style name for the given block.
459+
let blocks = [...this.resolveInheritance(), this];
460+
let styleInterface: ObjectDictionary<Styles> = {};
461+
for (let b of blocks) {
462+
let styles = b.all(true);
463+
for (let style of styles) {
464+
styleInterface[style.asSource()] = style;
465+
}
466+
}
467+
return styleInterface;
468+
}
469+
451470
/**
452471
* Fetch a dictionary of styles associated with this block, using any preset
453472
* selector as the key. If a given style doesn't have a preset selector, it
@@ -650,6 +669,35 @@ export class Block
650669
return false;
651670
}
652671

672+
/**
673+
* Gets all the blocks that are implemented by this block or by any ancestor.
674+
* This includes:
675+
* - This block.
676+
* - The blocks this block inherits from.
677+
* - The blocks the above blocks explicitly declare that they implement.
678+
* - The blocks all the above blocks implement transitively.
679+
* Such that `blockA.resolveImplementedBlocks().has(blockB)` is true iff
680+
* `blockA` implements the interface of `blockB`.
681+
*/
682+
resolveImplementedBlocks(): Set<Block> {
683+
if (this._resolveImplementedBlocksResult) {
684+
return this._resolveImplementedBlocksResult;
685+
}
686+
let implemented = new Set<Block>([this]);
687+
if (this._base) {
688+
unionInto(implemented, this._base.resolveImplementedBlocks());
689+
}
690+
for (let impl of this.getImplementedBlocks()) {
691+
unionInto(implemented, impl.resolveImplementedBlocks());
692+
}
693+
this._resolveImplementedBlocksResult = implemented;
694+
return implemented;
695+
}
696+
697+
isImplementationOf(other: Block): boolean {
698+
return this.resolveImplementedBlocks().has(other);
699+
}
700+
653701
/**
654702
* Objects that contain Blocks are often passed into assorted libraries' options
655703
* hashes. Some libraries like to `JSON.stringify()` their options to create

‎packages/@css-blocks/core/src/BlockTree/BlockClass.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,7 @@ export class BlockClass extends Style<BlockClass, Block, Block, Attribute> {
280280
}
281281

282282
/**
283-
* Adds a new Style for this Style to compose.
284-
* TODO: Currently, conditions are grouped exclusively by the 'and' operator.
285-
* We can abstract boolean operators to keep an internal representation
286-
* of logic between css and template files and only resolve them to the
287-
* requested language interface at rewrite time.
283+
* Checks whether this style composes another style.
288284
*/
289285
composes(style: Styles, resolve = true): boolean {
290286
let compositions = resolve ? this.resolveComposedStyles() : new Set(this._composedStyles);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { ObjectDictionary } from "@opticss/util";
2+
// Every CSS Block style is assigned a unique number that is globally unique
3+
export type GlobalStyleIndex = number;
4+
// This represents an index that is local to a specific block
5+
export type LocalStyleIndex = number;
6+
// For clarity as to what type of information the strings are
7+
export type Classname = string;
8+
export type OptimizedClassname = string;
9+
// this is a really fancy way to alias to `number`
10+
export type OutputClassnameIndex = Exclude<keyof AggregateRewriteData["outputClassnames"], string>;
11+
// this is a really fancy way to alias to `number`
12+
export type GlobalBlockIndex = Exclude<keyof AggregateRewriteData["blocks"], string>;
13+
// this is a really fancy way to alias to `number`
14+
export type OptimizationIndex = Exclude<keyof AggregateRewriteData["optimizations"], string>;
15+
16+
// These 5 lines are a compact AST for boolean expressions.
17+
// Normally an AST would use objects with more expressive keys, but we want a
18+
// more compact data structure in this AST for fewer bytes in our output.
19+
// An array represents a sub-expression and the first element in that array indicates the
20+
// sub-expression type.
21+
//
22+
// When a GlobalStyleIndex is encountered, that part of the boolean expression
23+
// is considered true iff the current input state has that GlobalStyleIndex applied.
24+
export enum Operator { AND = 1, OR = 2, NOT = 3 }
25+
export type ConditionalStyleExpression = AndStyleExpression | OrStyleExpression | NotStyleExpression;
26+
export type StyleExpression = number | ConditionalStyleExpression;
27+
export type AndStyleExpression = [Operator.AND, ...StyleExpression[]];
28+
export type OrStyleExpression = [Operator.OR, ...StyleExpression[]];
29+
export type NotStyleExpression = [Operator.NOT, StyleExpression];
30+
31+
export interface ConditionalStyle {
32+
style: GlobalBlockIndex;
33+
conditions: ConditionalStyleExpression;
34+
}
35+
36+
export interface StyleRequirements {
37+
// The key is a GlobalStyleIndex.
38+
//
39+
// Value is condition that must be met for this style to be applied
40+
// even if the style itself is not dynamic.
41+
[styleIndex: number]: ConditionalStyleExpression;
42+
}
43+
44+
export interface ImpliedStyles {
45+
// The key is a GlobalStyleIndex
46+
//
47+
// Value is an unordered set.
48+
// - GlobalStyleIndex: a style that is also applied in conjunction with the given style.
49+
// - string: public class name (block alias) that is also applied in conjunction with the given style.
50+
//
51+
// Note: This list is only the directly implied styles. The full implication
52+
// graph is resolved at runtime.
53+
[styleIndex: number]: Array<GlobalStyleIndex | string | ConditionalStyle>;
54+
}
55+
56+
export type OptimizationEntry = [OutputClassnameIndex, StyleExpression];
57+
58+
export interface AggregateRewriteData {
59+
// Maps a block's unique ID to an index of AggregateRewriteData["blocks"].
60+
blockIds: ObjectDictionary<GlobalBlockIndex>;
61+
blocks: Array<BlockInfo>;
62+
63+
// This is a list of all the class names that might be returned by the rewrite helper
64+
// with the exception of public class names (block aliases) that are found in the styleImplications.
65+
// Note: classnames from the original source that are not optimized are also returned here.
66+
// Note: classnames from the original source that the optimizer has flagged as obsolete are not listed here.
67+
outputClassnames: Array<OptimizedClassname>;
68+
styleRequirements: StyleRequirements;
69+
impliedStyles: ImpliedStyles;
70+
// Adds the class name to the output if the style expression matches the current input state.
71+
optimizations: Array<OptimizationEntry>;
72+
// possibleOptimizations: {
73+
// // Key is a GlobalStyleIndex.
74+
// // Value is a list of all outputs that might apply for the given GlobalStyleIndex.
75+
// [styleIndex: number]: Array<OptimizationIndex>;
76+
// };
77+
}
78+
79+
export interface BlockInfo {
80+
// The styles of this block
81+
// Note: this includes all the styles that are inherited but not overridden
82+
// but does not include the styles that are inherited but then overridden.
83+
blockInterfaceStyles: ObjectDictionary<LocalStyleIndex>;
84+
// Given a block that implements this block's interface or inherits from this interface
85+
// Get an array of GlobalStyleIndex values that directly correspond to the same index as BlockInfo["styles"].
86+
// Note: If an implementation inherits from this block, this array will contain
87+
// GlobalStyleIndex values from this BlockInfo's styles wherever those styles
88+
// are not overridden. Thus it is guaranteed that each value in `implementationStyles`
89+
// has the same length as the `styles` array.
90+
implementations: {
91+
// The key is a GlobalStyleIndex
92+
[blockIndex: number]: Array<GlobalStyleIndex | null>;
93+
};
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Analyzer } from "@css-blocks/core";
2+
import { TEMPLATE_TYPE } from "@css-blocks/ember-support";
3+
import { TemplateIntegrationOptions } from "@opticss/template-api";
4+
5+
export class EmberAnalyzer extends Analyzer<TEMPLATE_TYPE> {
6+
analyze(_dir: string, _entryPoints: string[]): Promise<Analyzer<"HandlebarsTemplate">> {
7+
throw new Error("Method not implemented.");
8+
}
9+
get optimizationOptions(): TemplateIntegrationOptions {
10+
return {
11+
rewriteIdents: {
12+
id: false,
13+
class: true,
14+
},
15+
analyzedAttributes: ["class"],
16+
analyzedTagnames: false,
17+
};
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
import { Block, Configuration, Style, isAttrValue, isBlockClass, isStyle } from "@css-blocks/core";
2+
import { StyleMapping } from "@opticss/template-api";
3+
import { ObjectDictionary } from "@opticss/util";
4+
import * as debugGenerator from "debug";
5+
6+
import { AggregateRewriteData, BlockInfo, ConditionalStyle, ConditionalStyleExpression, GlobalBlockIndex, GlobalStyleIndex, ImpliedStyles, LocalStyleIndex, Operator, OptimizationEntry, StyleRequirements } from "./AggregateRewriteData";
7+
import { EmberAnalyzer } from "./EmberAnalyzer";
8+
9+
const debug = debugGenerator("css-blocks:ember-app:runtime-data-generator");
10+
11+
export class RuntimeDataGenerator {
12+
blocks: Array<Block>;
13+
styleIndices: Map<Style, number>;
14+
blockIndices: Map<Block, number>;
15+
sourceClassIndices: Map<string, number>;
16+
outputClassIndices: Map<string, number>;
17+
styleMapping: StyleMapping;
18+
analyzer: EmberAnalyzer;
19+
config: Configuration;
20+
reservedClassNames: Set<string>;
21+
constructor(blocks: Array<Block>, styleMapping: StyleMapping, analyzer: EmberAnalyzer, config: Configuration, reservedClassNames: Set<string>) {
22+
this.blocks = blocks;
23+
this.styleIndices = new Map<Style, number>();
24+
this.blockIndices = new Map<Block, number>();
25+
this.sourceClassIndices = new Map<string, number>();
26+
this.outputClassIndices = new Map<string, number>();
27+
this.styleMapping = styleMapping;
28+
this.analyzer = analyzer;
29+
this.config = config;
30+
this.reservedClassNames = reservedClassNames;
31+
}
32+
blockIndex(block: Block): number {
33+
if (!this.blockIndices.has(block)) {
34+
this.blockIndices.set(block, this.blockIndices.size);
35+
}
36+
return this.blockIndices.get(block)!;
37+
}
38+
sourceClassIndex(className: string): number {
39+
if (!this.sourceClassIndices.has(className)) {
40+
this.sourceClassIndices.set(className, this.sourceClassIndices.size);
41+
}
42+
return this.sourceClassIndices.get(className)!;
43+
}
44+
cssClass(style: Style): string {
45+
return style.cssClass(this.config, this.reservedClassNames);
46+
}
47+
outputClassIndex(classNameOrStyle: string | Style): number {
48+
let className: string;
49+
if (isStyle(classNameOrStyle)) {
50+
className = this.cssClass(classNameOrStyle);
51+
} else {
52+
className = classNameOrStyle;
53+
}
54+
if (!this.outputClassIndices.has(className)) {
55+
this.outputClassIndices.set(className, this.outputClassIndices.size);
56+
}
57+
return this.outputClassIndices.get(className)!;
58+
}
59+
styleIndex(style: undefined): null;
60+
styleIndex(style: Style): number;
61+
styleIndex(style: Style | undefined): number | null {
62+
if (!style) return null;
63+
if (!this.styleIndices.has(style)) {
64+
this.styleIndices.set(style, this.styleIndices.size);
65+
}
66+
return this.styleIndices.get(style)!;
67+
}
68+
generate(): AggregateRewriteData {
69+
let blockIds: ObjectDictionary<GlobalBlockIndex> = {};
70+
let blocks = new Array<BlockInfo>();
71+
for (let block of this.blocks) {
72+
blockIds[block.guid] = this.blockIndex(block);
73+
}
74+
for (let block of this.blocks) {
75+
blocks[this.blockIndex(block)] = this.generateBlockInfo(block);
76+
}
77+
let stylesInUse = this.findStylesInUse();
78+
debug(`There are ${stylesInUse.size} styles in use.`);
79+
let styleRequirements: StyleRequirements = {};
80+
for (let style of stylesInUse) {
81+
if (isAttrValue(style)) {
82+
styleRequirements[this.styleIndex(style)] = [Operator.AND, this.styleIndex(style.blockClass)];
83+
}
84+
}
85+
86+
let impliedStyles = this.getImpliedStyles(stylesInUse);
87+
88+
let optimizations = this.getOptimizations(stylesInUse);
89+
90+
let outputClassnames = new Array<string>(this.outputClassIndices.size);
91+
for (let outputClass of this.outputClassIndices.keys()) {
92+
outputClassnames[this.outputClassIndices.get(outputClass)!] = outputClass;
93+
}
94+
95+
return {
96+
blockIds,
97+
blocks,
98+
outputClassnames,
99+
styleRequirements,
100+
impliedStyles,
101+
optimizations,
102+
};
103+
}
104+
105+
getOptimizations(stylesInUse: Set<Style>): Array<OptimizationEntry> {
106+
let optimizations = new Array<OptimizationEntry>();
107+
for (let style of stylesInUse) {
108+
if (this.styleMapping.isStyledAfterOptimization({name: "class", value: this.cssClass(style)})) {
109+
optimizations.push([this.outputClassIndex(style), this.styleIndex(style)]);
110+
continue;
111+
}
112+
}
113+
return optimizations;
114+
}
115+
116+
getImpliedStyles(stylesInUse: Set<Style>): ImpliedStyles {
117+
let impliedStyles: ImpliedStyles = {};
118+
for (let style of stylesInUse) {
119+
let implied = new Array<GlobalStyleIndex | string | ConditionalStyle>();
120+
// implied by inheritance
121+
let baseStyle = style.base;
122+
if (baseStyle) {
123+
implied.push(this.styleIndex(baseStyle));
124+
}
125+
126+
// implied by aliasing
127+
implied.push(...style.getStyleAliases());
128+
129+
// implied by composition
130+
if (isBlockClass(style)) {
131+
for (let composition of style.composedStyles()) {
132+
if (composition.conditions.length > 0) {
133+
let style = this.styleIndex(composition.style);
134+
let conditions: ConditionalStyleExpression = [Operator.AND, ...composition.conditions.map(s => this.styleIndex(s))];
135+
implied.push({style, conditions});
136+
} else {
137+
implied.push(this.styleIndex(composition.style));
138+
}
139+
}
140+
}
141+
if (implied.length > 0) {
142+
impliedStyles[this.styleIndex(style)] = implied;
143+
}
144+
}
145+
return impliedStyles;
146+
}
147+
148+
findStylesInUse(): Set<Style> {
149+
let stylesInUse = new Set<Style>();
150+
for (let style of this.analyzer.stylesFound) {
151+
for (let s of style.resolveStyles()) {
152+
stylesInUse.add(s);
153+
}
154+
if (isBlockClass(style)) {
155+
for (let c of style.resolveComposedStyles()) {
156+
stylesInUse.add(c.style);
157+
}
158+
}
159+
}
160+
return stylesInUse;
161+
}
162+
generateBlockInfo(block: Block): BlockInfo {
163+
let blockInterfaceStyles: ObjectDictionary<LocalStyleIndex> = {};
164+
let resolvedInterface = block.resolvedStyleInterface();
165+
let styleNames = Object.keys(resolvedInterface).sort();
166+
let i = 0;
167+
for (let styleName of styleNames) {
168+
blockInterfaceStyles[styleName] = i++;
169+
}
170+
let implementingBlocks = this.blocks.filter(b => b.isImplementationOf(block));
171+
let implementations: ObjectDictionary<Array<GlobalBlockIndex | null>> = {};
172+
for (let impl of implementingBlocks) {
173+
let implInterface = impl.resolvedStyleInterface();
174+
implementations[this.blockIndex(impl)] = styleNames.map(n => this.styleIndex(implInterface[n]));
175+
}
176+
return {
177+
blockInterfaceStyles,
178+
implementations,
179+
};
180+
}
181+
}

‎packages/@css-blocks/ember-app/src/brocolli-plugin.ts

+13-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { Analyzer, Block, BlockCompiler, BlockFactory, Options as CSSBlocksOptions, SerializedSourceAnalysis, resolveConfiguration } from "@css-blocks/core";
1+
import { Block, BlockCompiler, BlockFactory, Options as CSSBlocksOptions, SerializedSourceAnalysis, resolveConfiguration } from "@css-blocks/core";
22
import { BroccoliTreeImporter, EmberAnalysis, TEMPLATE_TYPE, pathToIdent } from "@css-blocks/ember-support";
3-
import { TemplateIntegrationOptions } from "@opticss/template-api";
43
import { unionInto } from "@opticss/util";
54
import mergeTrees = require("broccoli-merge-trees");
65
import type { InputNode } from "broccoli-node-api";
@@ -11,23 +10,10 @@ import * as FSTree from "fs-tree-diff";
1110
import { Optimizer, postcss } from "opticss";
1211
import * as path from "path";
1312

14-
const debug = debugGenerator("css-blocks:ember-app");
13+
import { EmberAnalyzer } from "./EmberAnalyzer";
14+
import { RuntimeDataGenerator } from "./RuntimeDataGenerator";
1515

16-
class EmberAnalyzer extends Analyzer<TEMPLATE_TYPE> {
17-
analyze(_dir: string, _entryPoints: string[]): Promise<Analyzer<"HandlebarsTemplate">> {
18-
throw new Error("Method not implemented.");
19-
}
20-
get optimizationOptions(): TemplateIntegrationOptions {
21-
return {
22-
rewriteIdents: {
23-
id: false,
24-
class: true,
25-
},
26-
analyzedAttributes: ["class"],
27-
analyzedTagnames: false,
28-
};
29-
}
30-
}
16+
const debug = debugGenerator("css-blocks:ember-app");
3117

3218
export class CSSBlocksApplicationPlugin extends Filter {
3319
appName: string;
@@ -60,7 +46,7 @@ export class CSSBlocksApplicationPlugin extends Filter {
6046
let analyzer = new EmberAnalyzer(factory);
6147
// TODO: Make this configurable from the ember app.
6248
let optimizerOptions = {
63-
enabled: true,
49+
enabled: false,
6450
rewriteIdents: {
6551
id: false,
6652
class: true,
@@ -87,6 +73,7 @@ export class CSSBlocksApplicationPlugin extends Filter {
8773
}
8874
}
8975
let compiler = new BlockCompiler(postcss, config);
76+
let reservedClassnames = analyzer.reservedClassNames();
9077
for (let block of blocksUsed) {
9178
let content: postcss.Result;
9279
let filename = importer.debugIdentifier(block.identifier, config);
@@ -96,7 +83,7 @@ export class CSSBlocksApplicationPlugin extends Filter {
9683
} else {
9784
debug(`Compiling stylesheet for optimization of ${filename}`);
9885
// XXX Do we need to worry about reservedClassnames here?
99-
content = compiler.compile(block, block.stylesheet!, new Set()).toResult();
86+
content = compiler.compile(block, block.stylesheet!, reservedClassnames).toResult();
10087
}
10188
optimizer.addSource({
10289
content,
@@ -116,10 +103,15 @@ export class CSSBlocksApplicationPlugin extends Filter {
116103
this.output.writeFileSync(optLogFileName, optimizationResult.actions.logStrings().join("\n"), "utf8");
117104
debug("Wrote css, sourcemap, and optimization log.");
118105

106+
let dataGenerator = new RuntimeDataGenerator([...blocksUsed], optimizationResult.styleMapping, analyzer, config, reservedClassnames);
107+
let data = dataGenerator.generate();
108+
let serializedData = JSON.stringify(data, undefined, " ");
109+
debug("CSS Blocks Data is: \n%s", serializedData);
110+
119111
this.output.writeFileSync(
120112
`${this.appName}/services/-css-blocks-data.js`,
121113
`// CSS Blocks Generated Data. DO NOT EDIT.
122-
export const data = {className: "it-worked"};
114+
export const data = ${serializedData};
123115
`);
124116
}
125117
}

‎packages/@css-blocks/jsx/test/multi-file-discover/multi-file-test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class Test {
1515
assert.equal(analyzer.analysisCount(), 2);
1616
assert.equal(analyzer.getAnalysis(0).blockCount(), 1);
1717
assert.equal(analyzer.getAnalysis(1).blockCount(), 1);
18-
assert.equal(analyzer.styleCount(), 3);
18+
assert.equal(analyzer.staticCount(), 3);
1919
});
2020
}
2121

@@ -24,7 +24,7 @@ export class Test {
2424
return parseFile("index.tsx", { baseDir: base }).then((analyzer: Analyzer) => {
2525
assert.equal(analyzer.analysisCount(), 2);
2626
assert.equal(analyzer.blockPromises.size, 1);
27-
assert.equal(analyzer.styleCount(), 2);
27+
assert.equal(analyzer.staticCount(), 2);
2828
});
2929
}
3030

@@ -33,7 +33,7 @@ export class Test {
3333
return parseFile("index.tsx", { baseDir: base, types: "typescript" }).then((analyzer: Analyzer) => {
3434
assert.equal(analyzer.analysisCount(), 3);
3535
assert.equal(analyzer.blockPromises.size, 3);
36-
assert.equal(analyzer.styleCount(), 4);
36+
assert.equal(analyzer.staticCount(), 4);
3737
});
3838
}
3939

@@ -42,7 +42,7 @@ export class Test {
4242
return parseFile("index.tsx", { baseDir: base }).then((analyzer: Analyzer) => {
4343
assert.equal(analyzer.analysisCount(), 2);
4444
assert.equal(analyzer.blockPromises.size, 2);
45-
assert.equal(analyzer.styleCount(), 3);
45+
assert.equal(analyzer.staticCount(), 3);
4646
});
4747
}
4848
}

0 commit comments

Comments
 (0)
Please sign in to comment.