Skip to content

Commit

Permalink
feat(eslint): add rule disallowing optional inputs (intershop#1121)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhhyi authored and paramaeder committed May 11, 2022
1 parent e0cb15b commit 5676f3e
Show file tree
Hide file tree
Showing 32 changed files with 107 additions and 42 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
}
],
"ish-custom-rules/no-object-literal-type-assertion": "warn",
"ish-custom-rules/no-optional-inputs": "warn",
"ish-custom-rules/no-return-undefined": "error",
"ish-custom-rules/no-star-imports-in-store": "error",
"ish-custom-rules/no-testbed-with-then": "error",
Expand Down
40 changes: 40 additions & 0 deletions eslint-rules/src/rules/no-optional-inputs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Selectors } from '@angular-eslint/utils';
import { AST_NODE_TYPES, TSESLint, TSESTree } from '@typescript-eslint/utils';

const messages = {
doNotUseOptionalOperatorOnInputs: 'Angular @Input() properties are optional by default.',
};

const noOptionalInputsRule: TSESLint.RuleModule<keyof typeof messages> = {
meta: {
messages,
type: 'problem',
fixable: 'code',
schema: [],
docs: {
description: 'Disallow optional inputs',
recommended: 'warn',
},
},
create: context => ({
[Selectors.INPUT_DECORATOR](node: TSESTree.Decorator): void {
if (
node.parent.type === AST_NODE_TYPES.PropertyDefinition &&
node.parent.key.type === AST_NODE_TYPES.Identifier &&
node.parent.key.parent.type === AST_NODE_TYPES.PropertyDefinition &&
node.parent.key.parent.optional
) {
const loc = node.parent.key.range[1];
context.report({
node: node.parent.key.parent,
messageId: 'doNotUseOptionalOperatorOnInputs',
fix(fixer) {
return fixer.removeRange([loc, loc + 1]);
},
});
}
},
}),
};

export default noOptionalInputsRule;
24 changes: 24 additions & 0 deletions eslint-rules/tests/no-optional-inputs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import noOptionalInputsRule from '../src/rules/no-optional-inputs';

import testRule from './rule-tester';

testRule(noOptionalInputsRule, {
valid: [
{
name: 'should not report when inputs do not use the optional operator',
code: 'export class MyComponent { @Input() foo: string; }',
},
],
invalid: [
{
name: 'should report when inputs use the optional operator',
code: 'export class MyComponent { @Input() foo?: string; }',
errors: [
{
messageId: 'doNotUseOptionalOperatorOnInputs',
},
],
output: 'export class MyComponent { @Input() foo: string; }',
},
],
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { CostCenter } from 'ish-core/models/cost-center/cost-center.model';
})
export class CostCenterBudgetComponent implements OnChanges {
@Input() costCenter: CostCenter;
@Input() progressBarClass?: string;
@Input() progressBarClass: string;

spentBudgetPercentage: number;
remainingBudgetPercentage: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { OrganizationManagementFacade } from '../../facades/organization-managem
})
export class CostCenterFormComponent implements OnInit {
@Input() form: FormGroup;
@Input() costCenter?: CostCenter;
@Input() costCenter: CostCenter;

fields$: Observable<FormlyFieldConfig[]>;
model$: Observable<{ budgetValue?: number; currency: string; costCenterManager?: string } & Partial<CostCenterBase>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface UserBudgetModel {
})
export class UserBudgetFormComponent implements OnInit, OnDestroy {
@Input() form: FormGroup;
@Input() budget?: UserBudget;
@Input() budget: UserBudget;

fields: FormlyFieldConfig[];
model: UserBudgetModel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { B2bUser } from '../../models/b2b-user/b2b-user.model';
export class UserProfileFormComponent implements OnInit {
@Input() form: FormGroup;
@Input() error: HttpError;
@Input() user?: B2bUser;
@Input() user: B2bUser;

fields: FormlyFieldConfig[];
model: Partial<B2bUser>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import { Price } from 'ish-core/models/price/price.model';
})
export class BudgetBarComponent implements OnChanges {
@Input() budget: Price;
@Input() spentBudget?: Price;
@Input() additionalAmount?: Price;
@Input() spentBudget: Price;
@Input() additionalAmount: Price;

budgetPercentage: number;
overflowPercentage: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { CompareFacade } from '../../facades/compare.facade';
})
@GenerateLazyComponent()
export class ProductAddToCompareComponent implements OnInit {
@Input() displayType?: string;
@Input() cssClass?: string;
@Input() displayType: string;
@Input() cssClass: string;

isInCompareList$: Observable<boolean>;
visible$: Observable<boolean>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class AccountOrderTemplateListComponent {
* The list of order templates of the customer.
*/
@Input() orderTemplates: OrderTemplate[];
@Input() columnsToDisplay?: OrderTemplateColumnsType[] = ['title', 'creationDate', 'lineItems', 'actions'];
@Input() columnsToDisplay: OrderTemplateColumnsType[] = ['title', 'creationDate', 'lineItems', 'actions'];

constructor(private orderTemplatesFacade: OrderTemplatesFacade, private translate: TranslateService) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { OrderTemplatePreferencesDialogComponent } from '../order-template-prefe
@GenerateLazyComponent()
export class BasketCreateOrderTemplateComponent implements OnDestroy {
@Input() products: LineItemView[];
@Input() cssClass?: string;
@Input() cssClass: string;
private destroy$ = new Subject<void>();

constructor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class OrderTemplatePreferencesDialogComponent implements OnInit {
*/
@Input() orderTemplate: OrderTemplate;

@Input() modalTitle?: string;
@Input() modalTitle: string;
/**
* Emits the data of the new order template to create.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import { SelectOrderTemplateModalComponent } from '../select-order-template-moda
})
@GenerateLazyComponent()
export class ProductAddToOrderTemplateComponent implements OnDestroy, OnInit {
@Input() displayType?: 'icon' | 'link' | 'animated' = 'link';
@Input() cssClass?: string;
@Input() displayType: 'icon' | 'link' | 'animated' = 'link';
@Input() cssClass: string;

disabled$: Observable<boolean>;
visible$: Observable<boolean>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import { PunchoutType, PunchoutUser } from '../../models/punchout-user/punchout-
changeDetection: ChangeDetectionStrategy.Default,
})
export class PunchoutUserFormComponent implements OnInit {
@Input() punchoutUser?: PunchoutUser;
@Input() punchoutUser: PunchoutUser;

/** for new users the punchout type is required */
@Input() punchoutType?: PunchoutType;
@Input() punchoutType: PunchoutType;
@Output() submitUser = new EventEmitter<PunchoutUser>();

submitted = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type QuoteColumnsType =
})
export class QuoteListComponent {
@Input() quotes: (Quote | QuoteRequest | QuoteStubFromAttributes)[] = [];
@Input() columnsToDisplay?: QuoteColumnsType[] = [
@Input() columnsToDisplay: QuoteColumnsType[] = [
'quoteNo',
'displayName',
'lineItems',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { GenerateLazyComponent } from 'ish-core/utils/module-loader/generate-laz
})
@GenerateLazyComponent()
export class ProductAddToQuoteComponent implements OnInit {
@Input() displayType?: 'icon' | 'link' = 'link';
@Input() cssClass?: string;
@Input() displayType: 'icon' | 'link' = 'link';
@Input() cssClass: string;

disabled$: Observable<boolean>;
visible$: Observable<boolean>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { GenerateLazyComponent } from 'ish-core/utils/module-loader/generate-laz
})
@GenerateLazyComponent()
export class TactonConfigureProductComponent implements OnInit {
@Input() displayType?: 'icon' | 'link' | 'list-button' = 'link';
@Input() displayType: 'icon' | 'link' | 'list-button' = 'link';

sku$: Observable<string>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import { SelectWishlistModalComponent } from '../select-wishlist-modal/select-wi
*/
@GenerateLazyComponent()
export class ProductAddToWishlistComponent implements OnDestroy, OnInit {
@Input() displayType?: 'icon' | 'link' | 'animated' = 'link';
@Input() cssClass?: string;
@Input() displayType: 'icon' | 'link' | 'animated' = 'link';
@Input() cssClass: string;

visible$: Observable<boolean>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class WishlistPreferencesDialogComponent implements OnInit {
/**
* Predefined wishlist to fill the form with, if there is no wishlist a new wishlist will be created
*/
@Input() wishlist?: Wishlist;
@Input() wishlist: Wishlist;

/**
* Emits the data of the new wishlist to create.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type DisplayType = 'tile' | 'row';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RetailSetPartsComponent implements OnInit {
@Input() displayType?: DisplayType = 'row';
@Input() displayType: DisplayType = 'row';

parts$: Observable<SkuQuantityType[]>;
visible$: Observable<boolean>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ export class ContentSlotComponent {
/**
* An optional flag that controls the rendering of the pagelets with the wrapped HTML content.
*/
@Input() wrapper?: boolean;
@Input() wrapper: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class BasketBuyerComponent implements OnInit, OnDestroy {
/**
* Router link for editing the order reference id. If a routerLink is given a link is displayed to route to an edit page.
*/
@Input() editRouterLink?: string;
@Input() editRouterLink: string;

customer$: Observable<Customer>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ export class InfoBoxComponent {
/**
* Translation key of the box title (or a title text).
*/
@Input() heading?: string;
@Input() heading: string;

/**
* Router link for Editing the displayed data. If a routerLink is given a link is displayed to route to an edit page
*/
@Input() editRouterLink?: string;
@Input() editRouterLink: string;

/**
* Additional css classes to be passed to the infobox div
*/
@Input() cssClass?: string;
@Input() cssClass: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { OrderLineItem } from 'ish-core/models/order/order.model';
export class LineItemListElementComponent implements OnInit {
@Input() pli: Partial<LineItemView & OrderLineItem>;
@Input() editable = true;
@Input() lineItemViewType?: 'simple' | 'availability';
@Input() lineItemViewType: 'simple' | 'availability';

constructor(private context: ProductContextFacade, private checkoutFacade: CheckoutFacade) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class LineItemListComponent {
@Input() lineItems: Partial<LineItemView & OrderLineItem>[];
@Input() editable = true;
@Input() total: Price;
@Input() lineItemViewType?: 'simple' | 'availability';
@Input() lineItemViewType: 'simple' | 'availability';

trackByFn(_: number, item: Partial<LineItemView & OrderLineItem>) {
return item.productSKU;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class OrderListComponent implements OnInit {
* The columns to be displayed.
* Default: All columns besides the buyer
*/
@Input() columnsToDisplay?: OrderColumnsType[] = [
@Input() columnsToDisplay: OrderColumnsType[] = [
'creationDate',
'orderNo',
'lineItems',
Expand All @@ -57,7 +57,7 @@ export class OrderListComponent implements OnInit {
* The orders to be displayed.
* Default: Orders of the current user are shown.
*/
@Input() orders?: Partial<Order>[];
@Input() orders: Partial<Order>[];

orders$: Observable<Partial<Order>[]>;
loading$: Observable<boolean>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ export class ProductAddToBasketComponent implements OnInit, OnDestroy {
/**
* when 'icon', the button label is an icon, otherwise it is text
*/
@Input() displayType?: 'icon' | 'link' = 'link';
@Input() displayType: 'icon' | 'link' = 'link';
/**
* additional css styling
*/
@Input() cssClass?: string;
@Input() cssClass: string;

basketLoading$: Observable<boolean>;
visible$: Observable<boolean>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class ProductImageComponent implements OnInit {
* If true, a product link is generated around the component or the given link target is taken
*/
@Input() link = false;
@Input() linkTarget?: string;
@Input() linkTarget: string;

@Input() queryParamsHandling: QueryParamsHandling = 'merge';
/**
Expand All @@ -34,11 +34,11 @@ export class ProductImageComponent implements OnInit {
/**
* The image view, e.g. 'front', 'back'.
*/
@Input() imageView?: string;
@Input() imageView: string;
/**
* A custom alt text for the img tag.
*/
@Input() altText?: string;
@Input() altText: string;

productURL$: Observable<string>;
productImage$: Observable<Image>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import { ViewType } from 'ish-core/models/viewtype/viewtype.types';
})
export class ProductListComponent implements OnInit {
@Input() products: string[];
@Input() categoryId?: string;
@Input() viewType?: ViewType = 'grid';
@Input() categoryId: string;
@Input() viewType: ViewType = 'grid';

listingLoading$: Observable<boolean>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { whenFalsy, whenTruthy } from 'ish-core/utils/operators';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProductListingComponent implements OnInit, OnChanges, OnDestroy {
@Input() categoryId?: string;
@Input() categoryId: string;
@Input() id: ProductListingID;
@Input() mode: 'endless-scrolling' | 'paging' = 'endless-scrolling';
@Input() fragmentOnRouting = 'product-list-top';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Promotion } from 'ish-core/models/promotion/promotion.model';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProductPromotionComponent implements OnInit {
@Input() displayType?: string;
@Input() displayType: string;

visible$: Observable<boolean>;
promotions$: Observable<Promotion[]>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class SearchBoxComponent implements OnInit, OnDestroy {
/**
* the search box configuration for this component
*/
@Input() configuration?: SearchBoxConfiguration;
@Input() configuration: SearchBoxConfiguration;

searchResults$: Observable<SuggestTerm[]>;
inputSearchTerms$ = new ReplaySubject<string>(1);
Expand Down

0 comments on commit 5676f3e

Please sign in to comment.