Skip to content

Commit

Permalink
feat: add quick fix to add @Suppress directive
Browse files Browse the repository at this point in the history
  • Loading branch information
Yogu committed Sep 6, 2024
1 parent 3bb7c41 commit 06c4ec0
Show file tree
Hide file tree
Showing 18 changed files with 476 additions and 56 deletions.
2 changes: 1 addition & 1 deletion spec/model/implementation/validation-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function expectQuickFix(
const result = validate(component);
const quickfixes = result.messages.flatMap((m) => m.quickFixes);
expect(quickfixes.map((q) => q.description)).to.include(expectedDescription);
const matchingQuickfixes = quickfixes.filter((q) => q.description);
const matchingQuickfixes = quickfixes.filter((q) => q.description === expectedDescription);
expect(matchingQuickfixes).to.have.a.lengthOf(1);
const quickfix = matchingQuickfixes[0];
const changeSet = quickfix.getChangeSet();
Expand Down
218 changes: 218 additions & 0 deletions spec/model/validation/suppress/quick-fix.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import { expectQuickFix } from '../../implementation/validation-utils';
import gql from 'graphql-tag';
import { Project } from '../../../../src/project/project';

describe('@suppress quick fix', () => {
it('generates a quick fix on type level', () => {
const project = new Project([
gql`
type Stuff @rootEntity {
foo: String
}
# comment before type
type Child @childEntity {
# comment in type
stuff: Int
}
`.loc!.source,
]);
expectQuickFix(
project,
'Suppress this warning',
`
type Stuff @rootEntity {
foo: String
}
# comment before type
type Child @childEntity @suppress(warnings: UNUSED) {
# comment in type
stuff: Int
}
`,
);
});

it('generates a quick fix on enum level', () => {
const project = new Project([
gql`
type Stuff @rootEntity {
value: myenum
}
enum myenum {
NAME1
NAME2
}
`.loc!.source,
]);
expectQuickFix(
project,
'Suppress this warning',
`
type Stuff @rootEntity {
value: myenum
}
enum myenum @suppress(warnings: NAMING) {
NAME1
NAME2
}
`,
);
});

it('generates a quick fix on enum value level', () => {
const project = new Project([
gql`
type Stuff @rootEntity {
value: MyEnum
}
enum MyEnum {
NAME1
name2
}
`.loc!.source,
]);
expectQuickFix(
project,
'Suppress this warning',
`
type Stuff @rootEntity {
value: MyEnum
}
enum MyEnum {
NAME1
name2 @suppress(warnings: NAMING)
}
`,
);
});

it('generates a quick fix on field level', () => {
const project = new Project([
gql`
type Stuff @rootEntity {
_key: String @key # after field
key: String
}
`.loc!.source,
]);
expectQuickFix(
project,
'Suppress this warning',
`
type Stuff @rootEntity {
_key: String @key @suppress(warnings: DEPRECATED) # after field
key: String
}
`,
);
});

it('generates a quick fix if there already is an empty @suppress directive', () => {
const project = new Project([
gql`
type Stuff @rootEntity {
_key: String @key @suppress
key: String
}
`.loc!.source,
]);
expectQuickFix(
project,
'Suppress this warning',
`
type Stuff @rootEntity {
_key: String @key @suppress(warnings: DEPRECATED)
key: String
}
`,
);
});

it('generates a quick fix if there already is a @suppress directive with a different arg', () => {
const project = new Project([
gql`
type Stuff @rootEntity {
_key: String @key @suppress(infos: NO_TYPE_CHECKS)
key: String
}
`.loc!.source,
]);
expectQuickFix(
project,
'Suppress this warning',
`
type Stuff @rootEntity {
_key: String @key @suppress(infos: NO_TYPE_CHECKS, warnings: DEPRECATED)
key: String
}
`,
);
});

it('generates a quick fix if there already is a @suppress directive with a single code', () => {
const project = new Project([
gql`
type Stuff @rootEntity {
_key: String @key @suppress(warnings: UNUSED)
key: String
}
`.loc!.source,
]);
expectQuickFix(
project,
'Suppress this warning',
`
type Stuff @rootEntity {
_key: String @key @suppress(warnings: [UNUSED, DEPRECATED])
key: String
}
`,
);
});

it('generates a quick fix if there already is a @suppress directive with a single code as a list', () => {
const project = new Project([
gql`
type Stuff @rootEntity {
_key: String @key @suppress(warnings: [UNUSED])
key: String
}
`.loc!.source,
]);
expectQuickFix(
project,
'Suppress this warning',
`
type Stuff @rootEntity {
_key: String @key @suppress(warnings: [UNUSED, DEPRECATED])
key: String
}
`,
);
});

it('generates a quick fix if there already is a @suppress directive with a multiple codes as a list', () => {
const project = new Project([
gql`
type Stuff @rootEntity {
_key: String @key @suppress(warnings: [UNUSED, NAMING])
key: String
}
`.loc!.source,
]);
expectQuickFix(
project,
'Suppress this warning',
`
type Stuff @rootEntity {
_key: String @key @suppress(warnings: [UNUSED, NAMING, DEPRECATED])
key: String
}
`,
);
});
});
2 changes: 2 additions & 0 deletions src/model/change-set/change-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export class ChangeSet {
this.textChanges = changes.filter((c) => c instanceof TextChange);
this.appendChanges = changes.filter((c) => c instanceof AppendChange);
}

static EMPTY = new ChangeSet([]);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/model/create-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ import { parseI18nConfigs } from './parse-i18n';
import { parseModuleConfigs } from './parse-modules';
import { parseTTLConfigs } from './parse-ttl';
import { ValidationContext, ValidationMessage } from './validation';
import { WarningCode } from '../schema/message-codes';
import { WarningCode } from './validation/suppress/message-codes';

export function createModel(parsedProject: ParsedProject, options: ModelOptions = {}): Model {
const validationContext = new ValidationContext();
Expand Down
2 changes: 1 addition & 1 deletion src/model/implementation/enum-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { EnumValueLocalization } from './i18n';
import { Model } from './model';
import { TypeBase } from './type-base';
import memorize from 'memorize-decorator';
import { WarningCode } from '../../schema/message-codes';
import { WarningCode } from '../validation/suppress/message-codes';

export class EnumType extends TypeBase {
constructor(input: EnumTypeConfig, model: Model) {
Expand Down
2 changes: 1 addition & 1 deletion src/model/implementation/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import { Relation, RelationSide } from './relation';
import { RolesSpecifier } from './roles-specifier';
import { InvalidType, ObjectType, Type } from './type';
import { ValueObjectType } from './value-object-type';
import { WarningCode } from '../../schema/message-codes';
import { WarningCode } from '../validation/suppress/message-codes';

export interface SystemFieldConfig extends FieldConfig {
readonly isSystemField?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/model/implementation/flex-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ModelComponent, ValidationContext } from '../validation/validation-cont
import { FlexSearchPrimarySortClauseConfig } from '../config';
import { RootEntityType } from './root-entity-type';
import { Severity, ValidationMessage } from '../validation';
import { WarningCode } from '../../schema/message-codes';
import { WarningCode } from '../validation/suppress/message-codes';

export const IDENTITY_ANALYZER = 'identity';
export const NORM_CI_ANALYZER = 'norm_ci';
Expand Down
2 changes: 1 addition & 1 deletion src/model/implementation/roles-specifier.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ModelComponent, ValidationContext } from '../validation/validation-context';
import { RolesSpecifierConfig } from '../config';
import { ValidationMessage } from '../validation';
import { WarningCode } from '../../schema/message-codes';
import { WarningCode } from '../validation/suppress/message-codes';
import { Type } from './type';
import { Field } from './field';

Expand Down
2 changes: 1 addition & 1 deletion src/model/implementation/root-entity-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { RolesSpecifier } from './roles-specifier';
import { ScalarType } from './scalar-type';
import { TimeToLiveType } from './time-to-live';
import { EffectiveModuleSpecification } from './modules/effective-module-specification';
import { WarningCode } from '../../schema/message-codes';
import { WarningCode } from '../validation/suppress/message-codes';

export class RootEntityType extends ObjectTypeBase {
private readonly permissions: PermissionsConfig & {};
Expand Down
2 changes: 1 addition & 1 deletion src/model/implementation/time-to-live.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { RootEntityType } from './root-entity-type';
import { ScalarType } from './scalar-type';
import { Type } from './type';
import { FieldPath } from './field-path';
import { WarningCode } from '../../schema/message-codes';
import { WarningCode } from '../validation/suppress/message-codes';

export class TimeToLiveType implements ModelComponent {
readonly cascadeFields: ReadonlyArray<FieldPath> = [];
Expand Down
2 changes: 1 addition & 1 deletion src/model/implementation/type-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { EffectiveModuleSpecification } from './modules/effective-module-specifi
import { MODULES_DIRECTIVE } from '../../schema/constants';
import { TypeModuleSpecification } from './modules/type-module-specification';
import { Type } from './type';
import { WarningCode } from '../../schema/message-codes';
import { WarningCode } from '../validation/suppress/message-codes';

export abstract class TypeBase implements ModelComponent {
readonly name: string;
Expand Down
Loading

0 comments on commit 06c4ec0

Please sign in to comment.