Skip to content

Commit

Permalink
handling simple imports
Browse files Browse the repository at this point in the history
  • Loading branch information
ascandone committed Nov 23, 2024
1 parent 93800e6 commit b207118
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 70 deletions.
74 changes: 39 additions & 35 deletions src/analysis/analyse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ describe("globals resolution", () => {
});
});

describe.todo("modules", () => {
describe("modules", () => {
test.todo("imports cannot shadow values");
test.todo("imports cannot shadow types");
test.todo("imports cannot shadow constructors");
Expand All @@ -215,8 +215,9 @@ describe.todo("modules", () => {

const [a] = performAnalysis(
`
pub let y = x
`,
// import A.{x}
pub let y = x
`,
{
dependencies: { A },
implicitImports: [
Expand All @@ -234,7 +235,7 @@ describe.todo("modules", () => {
});
});

test("implicitly imports types of the modules in the prelude", () => {
test.todo("implicitly imports types of the modules in the prelude", () => {
const [A] = performAnalysis(`type MyType {}`, { namespace: "A" });

Check warning on line 239 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L239

Added line #L239 was not covered by tests

const [a] = performAnalysis(
Expand Down Expand Up @@ -262,7 +263,7 @@ describe.todo("modules", () => {
expect(a.errors).toEqual([]); // TODO check assertion

Check warning on line 263 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L245-L263

Added lines #L245 - L263 were not covered by tests
});

test("implicitly imports variants of the modules in the prelude", () => {
test.todo("implicitly imports variants of the modules in the prelude", () => {
const [A] = performAnalysis(
`

Check warning on line 268 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L267-L268

Added lines #L267 - L268 were not covered by tests
pub(..) type MyType { A }
Expand Down Expand Up @@ -299,7 +300,7 @@ describe.todo("modules", () => {
});

Check warning on line 300 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L297-L300

Added lines #L297 - L300 were not covered by tests
});

test("handles nested type references from other modules", () => {
test.todo("handles nested type references from other modules", () => {
const [A] = performAnalysis(
`

Check warning on line 305 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L304-L305

Added lines #L304 - L305 were not covered by tests
pub(..) type T { T }
Expand All @@ -321,7 +322,7 @@ describe.todo("modules", () => {
});

Check warning on line 322 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L317-L322

Added lines #L317 - L322 were not covered by tests
});

test("detects unused imports when there are not exposed vars", () => {
test.todo("detects unused imports when there are not exposed vars", () => {
const [A] = performAnalysis(``, { namespace: "A" });
const [a] = performAnalysis(`import A`, {
dependencies: { A },
Expand All @@ -330,7 +331,7 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(UnusedImport);

Check warning on line 331 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L326-L331

Added lines #L326 - L331 were not covered by tests
});

test("detects unused exposed values", () => {
test.todo("detects unused exposed values", () => {
const [A] = performAnalysis(`pub let x = 42`, { namespace: "A" });
const [a] = performAnalysis(`import A.{x}`, {
dependencies: { A },
Expand All @@ -339,7 +340,7 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(UnusedExposing);

Check warning on line 340 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L335-L340

Added lines #L335 - L340 were not covered by tests
});

test("detects unused types", () => {
test.todo("detects unused types", () => {
const [A] = performAnalysis(`pub type T { }`, { namespace: "A" });
const [a] = performAnalysis(`import A.{T}`, {
dependencies: { A },
Expand All @@ -348,7 +349,7 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(UnusedExposing);

Check warning on line 349 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L344-L349

Added lines #L344 - L349 were not covered by tests
});

test("handles variants imports", () => {
test.todo("handles variants imports", () => {
const [A] = performAnalysis(`pub(..) type MyType { Constr }`, {
namespace: "A",
});

Check warning on line 355 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L353-L355

Added lines #L353 - L355 were not covered by tests
Expand All @@ -367,7 +368,7 @@ describe.todo("modules", () => {
});

Check warning on line 368 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L365-L368

Added lines #L365 - L368 were not covered by tests
});

test("handles nested imports", () => {
test.todo("handles nested imports", () => {
const [Mod] = performAnalysis(
`

Check warning on line 373 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L372-L373

Added lines #L372 - L373 were not covered by tests
pub let x = 42
Expand All @@ -389,7 +390,7 @@ describe.todo("modules", () => {
});

Check warning on line 390 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L387-L390

Added lines #L387 - L390 were not covered by tests
});

test("allow importing types (unqualified)", () => {
test.todo("allow importing types (unqualified)", () => {
const [Mod] = performAnalysis(`pub type Example { }`, { namespace: "Mod" });

Check warning on line 394 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L394

Added line #L394 was not covered by tests

const [a] = performAnalysis(
Expand All @@ -406,7 +407,7 @@ describe.todo("modules", () => {
});

Check warning on line 407 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L404-L407

Added lines #L404 - L407 were not covered by tests
});

test("allow importing types (qualified)", () => {
test.todo("allow importing types (qualified)", () => {
const [Mod] = performAnalysis(`pub type Example { }`, { namespace: "Mod" });
const [a] = performAnalysis(
`

Check warning on line 413 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L411-L413

Added lines #L411 - L413 were not covered by tests
Expand All @@ -422,7 +423,7 @@ describe.todo("modules", () => {
});

Check warning on line 423 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L420-L423

Added lines #L420 - L423 were not covered by tests
});

test("allow using imported types in match patterns", () => {
test.todo("allow using imported types in match patterns", () => {
const [Mod] = performAnalysis(`pub(..) type T { Constr }`, {
namespace: "Mod",
});
Expand All @@ -439,13 +440,13 @@ describe.todo("modules", () => {
expect(a.errors).toEqual([]);

Check warning on line 440 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L440

Added line #L440 was not covered by tests
});

test("error when import a non-existing module", () => {
test.todo("error when import a non-existing module", () => {
const [a] = performAnalysis(`import ModuleNotFound`);
expect(a.errors).toHaveLength(1);
expect(a.errors[0]?.description).toBeInstanceOf(UnboundModule);

Check warning on line 446 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L444-L446

Added lines #L444 - L446 were not covered by tests
});

test("error when importing a non-existing type", () => {
test.todo("error when importing a non-existing type", () => {
const [Mod] = performAnalysis(``, { namespace: "Mod" });
const [a] = performAnalysis(`import Mod.{NotFound}`, {
dependencies: { Mod },
Expand All @@ -454,7 +455,7 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(NonExistingImport);

Check warning on line 455 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L450-L455

Added lines #L450 - L455 were not covered by tests
});

test("error when importing a type the is not pub", () => {
test.todo("error when importing a type the is not pub", () => {
const [Mod] = performAnalysis(`type PrivateType {}`, { namespace: "Mod" });
const [a] = performAnalysis(`import Mod.{PrivateType}`, {
dependencies: { Mod },
Expand All @@ -463,7 +464,7 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(NonExistingImport);

Check warning on line 464 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L459-L464

Added lines #L459 - L464 were not covered by tests
});

test("error when importing a non-existing value", () => {
test.todo("error when importing a non-existing value", () => {
const [Mod] = performAnalysis(``, { namespace: "Mod" });
const [a] = performAnalysis(`import Mod.{not_found}`, {
dependencies: { Mod },
Expand All @@ -472,7 +473,7 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(NonExistingImport);

Check warning on line 473 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L468-L473

Added lines #L468 - L473 were not covered by tests
});

test("error when importing a private value", () => {
test.todo("error when importing a private value", () => {
const [Mod] = performAnalysis(`let not_found = 42`, { namespace: "Mod" });
const [a] = performAnalysis(`import Mod.{not_found}`, {
dependencies: { Mod },
Expand All @@ -482,7 +483,7 @@ describe.todo("modules", () => {
).toBeTruthy();

Check warning on line 483 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L477-L483

Added lines #L477 - L483 were not covered by tests
});

test("qualified imports should not work on priv functions", () => {
test.todo("qualified imports should not work on priv functions", () => {
const [Mod] = performAnalysis(`let not_found = 42`, { namespace: "Mod" });
const [a] = performAnalysis(
`

Check warning on line 489 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L487-L489

Added lines #L487 - L489 were not covered by tests
Expand All @@ -496,7 +497,7 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(NonExistingImport);

Check warning on line 497 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L496-L497

Added lines #L496 - L497 were not covered by tests
});

test("qualified imports should not work on priv constructors", () => {
test.todo("qualified imports should not work on priv constructors", () => {
const [Mod] = performAnalysis(`pub type T { A }`, { namespace: "Mod" });
const [a] = performAnalysis(
`

Check warning on line 503 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L501-L503

Added lines #L501 - L503 were not covered by tests
Expand Down Expand Up @@ -524,7 +525,7 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(UnboundType);
});

test("error when expose impl is run on a extern type", () => {
test.todo("error when expose impl is run on a extern type", () => {
const [Mod] = performAnalysis(`extern pub type ExternType`, {
namespace: "Mod",
});
Expand All @@ -535,7 +536,7 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(BadImport);

Check warning on line 536 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L529-L536

Added lines #L529 - L536 were not covered by tests
});

test("error when expose impl is run on a opaque type", () => {
test.todo("error when expose impl is run on a opaque type", () => {
// Note it is `pub` instead of `pub(..)`
const [Mod] = performAnalysis(`pub type T {}`, { namespace: "Mod" });
const [a] = performAnalysis(`import Mod.{T(..)}`, {
Expand All @@ -545,28 +546,31 @@ describe.todo("modules", () => {
expect(a.errors[0]?.description).toBeInstanceOf(BadImport);

Check warning on line 546 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L541-L546

Added lines #L541 - L546 were not covered by tests
});

test("error when qualifier is not an imported module", () => {
test.todo("error when qualifier is not an imported module", () => {
const [a] = performAnalysis(`pub let x = NotImported.value`);
expect(a.errors).toHaveLength(1);
expect(a.errors[0]?.description).toBeInstanceOf(UnimportedModule);

Check warning on line 552 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L550-L552

Added lines #L550 - L552 were not covered by tests
});

test("types from different modules with the same name aren't treated the same", () => {
const [Mod] = performAnalysis(`pub(..) type T { Constr }`, {
namespace: "Mod",
});
const [a] = performAnalysis(
`
test.todo(
"types from different modules with the same name aren't treated the same",
() => {
const [Mod] = performAnalysis(`pub(..) type T { Constr }`, {
namespace: "Mod",
});
const [a] = performAnalysis(
`

Check warning on line 562 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L558-L562

Added lines #L558 - L562 were not covered by tests
import Mod
type T { Constr }
pub let t: T = Mod.Constr
`,
{ dependencies: { Mod } },
);
{ dependencies: { Mod } },
);

Check warning on line 568 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L567-L568

Added lines #L567 - L568 were not covered by tests

expect(a.errors).toHaveLength(1);
expect(a.errors[0]?.description).toBeInstanceOf(TypeMismatch_REWRITE);
});
expect(a.errors).toHaveLength(1);
expect(a.errors[0]?.description).toBeInstanceOf(TypeMismatch_REWRITE);
},

Check warning on line 572 in src/analysis/analyse.test.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.test.ts#L570-L572

Added lines #L570 - L572 were not covered by tests
);
});

describe("named types", () => {
Expand Down
36 changes: 29 additions & 7 deletions src/analysis/analyse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,24 @@ export class Analysis {
public readonly module: UntypedModule,
public readonly options: AnalyseOptions = {},
) {
const getDependencyResolutionAnalysis = (
ns: string,
): ResolutionAnalysis | undefined => {
const dep = options.getDependency?.(ns);
if (dep === undefined) {
return undefined;
}

Check warning on line 61 in src/analysis/analyse.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.ts#L60-L61

Added lines #L60 - L61 were not covered by tests
return dep.resolution;
};

const emitError = this.errors.push.bind(this.errors);
this.resolution = new ResolutionAnalysis(
this.package_,
ns,
module,
emitError,
getDependencyResolutionAnalysis,
options.implicitImports,
);
this.typesHydration = new TypeAstsHydration(
this.package_,
Expand Down Expand Up @@ -108,17 +120,27 @@ export class Analysis {
) {
switch (resolution.type) {
case "global-variable": {
const poly = this.getRawType(resolution.declaration.binding);

const isSelfRecursive = this.currentDeclarationGroup.includes(
const isRecursive = this.currentDeclarationGroup.includes(
resolution.declaration,
);
if (isRecursive) {
const mono = this.getRawType(resolution.declaration.binding);
this.unifyNode(expr, mono);
return;
}

this.unifyNode(
expr,
isSelfRecursive ? poly : this.unifier.instantiate(poly, true),
);
const analysis =
resolution.namespace === this.ns
? this
: this.options.getDependency?.(resolution.namespace);

if (analysis === undefined) {
// probably unreachable
throw new Error("TODO handle");

Check warning on line 139 in src/analysis/analyse.ts

View check run for this annotation

Codecov / codecov/patch

src/analysis/analyse.ts#L139

Added line #L139 was not covered by tests
}

const poly = analysis.getType(resolution.declaration.binding);
this.unifyNode(expr, this.unifier.instantiate(poly, false));
return;
}

Expand Down
Loading

0 comments on commit b207118

Please sign in to comment.