# package-no-import-cycle

Source: https://apigenie.pl/docs/linter/protobuf/rules/package-no-import-cycle

This rule checks whether packages import each other in a cycle.

## Rule Details

Even when no file imports itself through a chain of imports, two packages can depend on each
other: a file of package A imports a file of package B, and another file of package B imports a
file of package A. Code generators that turn Protobuf packages into packages of the target
language, like the Go one, produce code with an import cycle that does not compile.

The `package-no-import-cycle` rule builds the graph of the packages: package A imports package B
when any file of A imports a file of B. For every import of the linted file that refers to a file
of another package, it looks for a path in this graph from that package back to the package of
the linted file. If there is one, it reports:

`Import '<import>' creates a package import cycle: <package> -> ... -> <package>`

The cycle starts and ends with the package of the linted file. Each imported package is reported
once per file, at the first import that leads to it.

The graph contains the files the linter knows about: the files being linted, the other `.proto`
files in their directories, and the files these import, directly or indirectly. Imports that
cannot be found are ignored. Files without a package are not checked, and are not part of the
graph.

## Configuration

This rule has no options.

## Examples

**Good**. `acme/pets/v1/pet.proto` imports a file of `acme.owners.v1`, which does not import
anything from `acme.pets.v1`.

```proto
syntax = "proto3";

package acme.pets.v1;

import "acme/owners/v1/owner.proto";

message Pet {
  string name = 1;
  acme.owners.v1.Owner owner = 2;
}
```

**Bad**. The same `acme/pets/v1/pet.proto`, while `acme/owners/v1/owner.proto` imports another
file of `acme.pets.v1`:

```proto
syntax = "proto3";

package acme.owners.v1;

import "acme/pets/v1/kind.proto";

message Owner {
  string name = 1;
  repeated acme.pets.v1.Kind preferred_kinds = 2;
}
```

No file imports itself, but when `pet.proto` is linted, the linter reports:

`Import 'acme/owners/v1/owner.proto' creates a package import cycle: acme.pets.v1 -> acme.owners.v1 -> acme.pets.v1`

## When Not to Use It

We recommend to always enable this rule. To accept an import that is part of a known cycle, add
an `// apigenie-lint-disable package-no-import-cycle` comment to the import statement.

## Compatibility

This rule is compatible with proto3 files. proto2 and editions files are rejected by the reader
and are not linted. The rule reads the imported files, found in the import paths and in the
directories above the importing file, and the other files in the directories of the linted files.
