mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
move tslint ADF rules in principal repo (#3247)
* move tslint ADF rules in principal repo * fix style issues * change pacakge.json position * update to angular cli 6.0.0 * reorganization package.json * remove node modules2 folder * exclude integration * rollback alfresco-js-api * solve types problems * fix pdf test * fix errors and exclude two tests * fix e2e * fix test * copy all the new packages in node_modules * fix test * fix packaging script * scss issue fix * move test export in tools
This commit is contained in:
5171
tools/export-check/export-2.0.0.json
Normal file
5171
tools/export-check/export-2.0.0.json
Normal file
File diff suppressed because it is too large
Load Diff
5591
tools/export-check/export-2.1.0.json
Normal file
5591
tools/export-check/export-2.1.0.json
Normal file
File diff suppressed because it is too large
Load Diff
5882
tools/export-check/export-2.2.0.json
Normal file
5882
tools/export-check/export-2.2.0.json
Normal file
File diff suppressed because it is too large
Load Diff
6460
tools/export-check/export-2.3.0.json
Normal file
6460
tools/export-check/export-2.3.0.json
Normal file
File diff suppressed because it is too large
Load Diff
9
tools/export-check/export-check-config.json
Normal file
9
tools/export-check/export-check-config.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"export-last-version": "export-new.json",
|
||||
"export-versions": [
|
||||
"export-2.0.0.json",
|
||||
"export-2.1.0.json",
|
||||
"export-2.2.0.json",
|
||||
"export-2.3.0.json"
|
||||
]
|
||||
}
|
6602
tools/export-check/export-new.json
Normal file
6602
tools/export-check/export-new.json
Normal file
File diff suppressed because it is too large
Load Diff
373
tools/export-check/exportCheck.ts
Normal file
373
tools/export-check/exportCheck.ts
Normal file
@@ -0,0 +1,373 @@
|
||||
import * as ts from "typescript";
|
||||
import * as fs from "fs";
|
||||
import chalk from "chalk";
|
||||
|
||||
var nconf = require('nconf');
|
||||
var basePath = "./tools/export-check/";
|
||||
|
||||
nconf.add('config', { type: 'file', file: `${basePath}export-check-config.json` });
|
||||
|
||||
var newLibExports = basePath + nconf.get('export-last-version');
|
||||
var exportFilesVersions = nconf.get('export-versions').map((currentFile) => {
|
||||
return basePath + currentFile;
|
||||
});
|
||||
|
||||
interface DocEntry {
|
||||
position?: {
|
||||
line: number,
|
||||
character: number,
|
||||
fileName: string
|
||||
},
|
||||
name?: string,
|
||||
skipError?: boolean
|
||||
};
|
||||
|
||||
let error_array = [];
|
||||
let warning_array = [];
|
||||
let exportedAllPath: Array<string> = [];
|
||||
let classList: Array<any> = [];
|
||||
|
||||
let add_error = function (error: string, nameClass: string) {
|
||||
let findErrorClass = false;
|
||||
|
||||
error_array.forEach((currentError) => {
|
||||
|
||||
if (currentError.nameClass === nameClass) {
|
||||
findErrorClass = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if (!findErrorClass) {
|
||||
error_array.push({
|
||||
error: error,
|
||||
nameClass: nameClass
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let count_error = 0;
|
||||
let count_warning = 0;
|
||||
|
||||
let print_errors = function () {
|
||||
error_array.forEach((current_error) => {
|
||||
console.log(chalk.red(`[${++count_error}] ${current_error.error}\n`));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
let add_warning = function (warning: string, nameClass: string, arrayCall: string[]) {
|
||||
|
||||
let findWarningClass = false;
|
||||
|
||||
warning_array.forEach((currentWarning) => {
|
||||
|
||||
if (currentWarning.nameClass === nameClass) {
|
||||
findWarningClass = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if (!findWarningClass) {
|
||||
warning_array.push({
|
||||
warning: warning,
|
||||
nameClass: nameClass,
|
||||
arrayCall: arrayCall
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let print_warnings = function () {
|
||||
warning_array.forEach((current_warning) => {
|
||||
console.log(chalk.yellow(`[${++count_warning}] ${current_warning.warning} \n ${current_warning.arrayCall} \n`));
|
||||
});
|
||||
}
|
||||
|
||||
let currentErrorPostion = function (exportEntry) {
|
||||
return ` ${exportEntry.position.fileName} (${exportEntry.position.line},${exportEntry.position.character})`
|
||||
}
|
||||
|
||||
let check_export = function (exportLastMajor: any, exportNew: any) {
|
||||
|
||||
exportLastMajor.forEach((currentexportLastMajor) => {
|
||||
|
||||
let currentexportNew = exportNew.filter((currentexportNew) => {
|
||||
return currentexportNew.name === currentexportLastMajor.name;
|
||||
});
|
||||
|
||||
if (currentexportNew.length > 1) {
|
||||
|
||||
let arrayCall = [];
|
||||
|
||||
currentexportNew.forEach((error) => {
|
||||
arrayCall.push(`${currentErrorPostion(error)}`);
|
||||
})
|
||||
|
||||
add_warning(`Multiple export ${currentexportNew[0].name} times ${currentexportNew.length}`, currentexportNew[0].name, arrayCall);
|
||||
|
||||
} else if (currentexportNew.length === 0) {
|
||||
if (!currentexportLastMajor.skipError) {
|
||||
add_error(`Not find export ${currentexportLastMajor.name} , old path: [${currentErrorPostion(currentexportLastMajor)}]`, currentexportLastMajor.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let expandStarExport = function (node: ts.Node): ts.ExportDeclaration {
|
||||
const ed = node as ts.Node as ts.ExportDeclaration;
|
||||
const exports = [{ name: "x" }];
|
||||
const exportSpecifiers = exports.map(e => ts.createExportSpecifier(e.name, e.name));
|
||||
const exportClause = ts.createNamedExports(exportSpecifiers);
|
||||
const newEd = ts.updateExportDeclaration(ed, ed.decorators, ed.modifiers, exportClause, ed.moduleSpecifier);
|
||||
|
||||
return newEd as ts.ExportDeclaration
|
||||
};
|
||||
|
||||
/** Generate documentation for all classes in a set of .ts files */
|
||||
function generatExportList(fileNames: string[], options: ts.CompilerOptions): void {
|
||||
// Build a program using the set of root file names in fileNames
|
||||
let program = ts.createProgram(fileNames, options);
|
||||
// Get the checker, we will use it to find more about classes
|
||||
let checker = program.getTypeChecker();
|
||||
|
||||
let exportCurrentVersion: DocEntry[] = [];
|
||||
|
||||
// Visit every sourceFile in the program
|
||||
for (const sourceFile of program.getSourceFiles()) {
|
||||
if (!sourceFile.isDeclarationFile) {
|
||||
// Walk the tree to search for classes
|
||||
ts.forEachChild(sourceFile, visit);
|
||||
}
|
||||
}
|
||||
|
||||
classList.forEach((classNode) => {
|
||||
if (classNode.symbol.parent) {
|
||||
let pathClass = classNode.symbol.parent.escapedName.replace(/"/g, "");
|
||||
|
||||
exportedAllPath.forEach((currenPath) => {
|
||||
let pathNoExtension = currenPath.replace(/\.[^/.]+$/, "");
|
||||
|
||||
if (pathNoExtension === pathClass) {
|
||||
// console.log('pathClass'+ pathClass);
|
||||
// console.log('pathNoExtension '+ pathNoExtension);
|
||||
extractExport(classNode);
|
||||
return;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
exportCurrentVersion.sort((nameA, nameB) => nameA.name.localeCompare(nameB.name));
|
||||
|
||||
console.log(chalk.green(`Saving new export in ${newLibExports}`));
|
||||
|
||||
fs.writeFileSync(newLibExports, JSON.stringify(exportCurrentVersion, undefined, 4));
|
||||
|
||||
var exportNewJSON = JSON.parse(JSON.stringify(exportCurrentVersion));
|
||||
|
||||
exportFilesVersions.forEach((currentExportVersionFile) => {
|
||||
|
||||
error_array = [];
|
||||
warning_array = [];
|
||||
|
||||
try {
|
||||
var currentExportVersionJSON = JSON.parse(fs.readFileSync(`${currentExportVersionFile}`, 'utf8'));
|
||||
} catch (error) {
|
||||
console.log(chalk.red(`${currentExportVersionFile} json not present`));
|
||||
throw new Error(`Undetected export comapring file ${currentExportVersionFile}`);
|
||||
}
|
||||
|
||||
|
||||
console.log(chalk.green(`Comparing ${newLibExports} and ${currentExportVersionFile}`));
|
||||
|
||||
check_export(currentExportVersionJSON, exportNewJSON);
|
||||
|
||||
print_warnings();
|
||||
print_errors();
|
||||
|
||||
|
||||
if (error_array.length > 0) {
|
||||
throw new Error('Export problems detected');
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
function extractExport(node: ts.Node) {
|
||||
//skip file with export-check: exclude comment
|
||||
if (node.getFullText(node.getSourceFile()).indexOf('export-check: exclude') > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { line, character } = node.getSourceFile().getLineAndCharacterOfPosition(node.getStart());
|
||||
//console.log(line + " " + character + " " + node.getSourceFile().fileName);
|
||||
|
||||
let symbol = checker.getSymbolAtLocation(node);
|
||||
|
||||
if (symbol) {
|
||||
let arryCalls = recursiveStackSave(node);
|
||||
|
||||
let className: any = symbol.escapedName;
|
||||
let filename = node.getSourceFile().fileName.substring(node.getSourceFile().fileName.indexOf('lib'), node.getSourceFile().fileName.length);
|
||||
exportCurrentVersion.push(serializeClass(className, line, character, filename, arryCalls));
|
||||
|
||||
// if (className === "ContentMetadataService") {
|
||||
// console.log(chalk.red("exportedAllPath" + exportedAllPath));
|
||||
// console.log(chalk.red("ContentMetadataService"));
|
||||
// recursiveStack(node);
|
||||
// }
|
||||
|
||||
} else {
|
||||
|
||||
let arryCalls = recursiveStackSave(node);
|
||||
|
||||
let className: any = (node as ts.ClassDeclaration).name.escapedText;
|
||||
let filename = node.getSourceFile().fileName.substring(node.getSourceFile().fileName.indexOf('lib'), node.getSourceFile().fileName.length);
|
||||
exportCurrentVersion.push(serializeClass(className, line, character, filename, arryCalls));
|
||||
|
||||
// if (className === "ContentMetadataService") {
|
||||
// console.log(chalk.greenBright("exportedAllPath" + exportedAllPath));
|
||||
// console.log(chalk.greenBright("ContentMetadataService"));
|
||||
// recursiveStack(node);
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function recursiveStackSave(node: ts.Node, arrayCalls?: string[]) {
|
||||
if (!arrayCalls) {
|
||||
arrayCalls = [];
|
||||
}
|
||||
|
||||
let filename = node.getSourceFile().fileName.substring(node.getSourceFile().fileName.indexOf('lib'), node.getSourceFile().fileName.length);
|
||||
let { line, character } = node.getSourceFile().getLineAndCharacterOfPosition(node.getStart());
|
||||
|
||||
arrayCalls.push(node.getSourceFile().fileName);
|
||||
|
||||
if (node.parent) {
|
||||
recursiveStackSave(node.parent, arrayCalls)
|
||||
}
|
||||
|
||||
return arrayCalls;
|
||||
|
||||
}
|
||||
|
||||
function recursiveStack(node: ts.Node) {
|
||||
let filename = node.getSourceFile().fileName.substring(node.getSourceFile().fileName.indexOf('lib'), node.getSourceFile().fileName.length);
|
||||
let { line, character } = node.getSourceFile().getLineAndCharacterOfPosition(node.getStart());
|
||||
console.log(chalk.bgCyan(line + " " + character + " " + node.getSourceFile().fileName));
|
||||
|
||||
if (node.parent) {
|
||||
recursiveStack(node.parent)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** visit nodes finding exported classes */
|
||||
function visit(node: ts.Node) {
|
||||
// Only consider exported nodes
|
||||
|
||||
if (node.kind === ts.SyntaxKind.ClassDeclaration) {
|
||||
|
||||
if (node.decorators) {
|
||||
node.decorators.forEach((decorator) => {
|
||||
visit(decorator as ts.Node);
|
||||
});
|
||||
}
|
||||
|
||||
classList.push(node);
|
||||
}
|
||||
|
||||
if (node.kind === ts.SyntaxKind.PropertyAssignment) {
|
||||
const initializer = (node as ts.PropertyAssignment).initializer;
|
||||
|
||||
visit(initializer as ts.Node);
|
||||
}
|
||||
|
||||
if (node.kind === ts.SyntaxKind.Identifier) {
|
||||
extractExport(node);
|
||||
}
|
||||
|
||||
if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) {
|
||||
(node as ts.ArrayLiteralExpression).elements.forEach((element) => {
|
||||
visit(element as ts.Node);
|
||||
});
|
||||
}
|
||||
|
||||
if (node.kind === ts.SyntaxKind.Decorator &&
|
||||
((node as ts.Decorator).expression as any).expression.text === "NgModule") {
|
||||
|
||||
((node as ts.Decorator).expression as any).arguments.forEach((argument) => {
|
||||
argument.properties.forEach((property) => {
|
||||
if (property.name.escapedText === "exports") {
|
||||
visit(property as ts.Node);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (ts.isExportDeclaration(node)) {
|
||||
if (node.exportClause) {
|
||||
node.exportClause.elements.forEach(exportCurrent => {
|
||||
extractExport(exportCurrent as ts.Node);
|
||||
});
|
||||
} else {
|
||||
(node.parent as any).resolvedModules.forEach((currentModule) => {
|
||||
|
||||
if (currentModule) {
|
||||
let find;
|
||||
exportedAllPath.forEach((currentExported) => {
|
||||
if (currentModule.resolvedFileName === currentExported) {
|
||||
find = currentExported;
|
||||
}
|
||||
})
|
||||
|
||||
if (!find) {
|
||||
exportedAllPath.push(currentModule.resolvedFileName);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
visit(node.moduleSpecifier);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ts.isModuleDeclaration(node)) {
|
||||
// This is a namespace, visit its children
|
||||
ts.forEachChild(node, visit);
|
||||
}
|
||||
}
|
||||
|
||||
/** Serialize a symbol into a json object */
|
||||
function serializeSymbol(className: string, line?: number, character?: number, fileName?: string, arryCalls?: string[]): DocEntry {
|
||||
|
||||
return {
|
||||
position: {
|
||||
line: line,
|
||||
character: character,
|
||||
fileName: fileName
|
||||
},
|
||||
name: className
|
||||
};
|
||||
}
|
||||
|
||||
/** Serialize a class symbol information */
|
||||
function serializeClass(className: string, line?: number, character?: number, fileName?: string, arryCalls?: string[]) {
|
||||
let details = serializeSymbol(className, line, character, fileName, arryCalls);
|
||||
|
||||
return details;
|
||||
}
|
||||
|
||||
/** True if this is visible outside this file, false otherwise */
|
||||
function isNodeExported(node: ts.Node): boolean {
|
||||
return (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) !== 0 || (!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
generatExportList(process.argv.slice(2), {
|
||||
target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS, removeComments: false
|
||||
});
|
7
tools/tslint-rules/.gitignore
vendored
Normal file
7
tools/tslint-rules/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/npm-debug.log
|
||||
/.idea
|
||||
node_modules
|
||||
coverage
|
||||
/temp/
|
||||
local.log
|
||||
/rules/*.js
|
16
tools/tslint-rules/.npmignore
Normal file
16
tools/tslint-rules/.npmignore
Normal file
@@ -0,0 +1,16 @@
|
||||
.idea
|
||||
|
||||
coverage/
|
||||
node_modules
|
||||
temp/
|
||||
test/
|
||||
|
||||
/.editorconfig
|
||||
/.travis.yml
|
||||
/gulpfile.js
|
||||
/.npmignore
|
||||
|
||||
*.tgz
|
||||
|
||||
/assets/
|
||||
local.log
|
36
tools/tslint-rules/README.md
Normal file
36
tools/tslint-rules/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# adf-tslint-rules
|
||||
|
||||
|
||||
A set of [TSLint](https://github.com/palantir/tslint) rules used on [ADF](https://github.com/Alfresco/alfresco-ng2-components) project.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm install adf-tslint-rules
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```javascript
|
||||
{
|
||||
"rulesDirectory": [
|
||||
"node_modules/codelyzer",
|
||||
"node_modules/adf-tslint-rules"
|
||||
],
|
||||
"rules": {
|
||||
"adf-file-name": true,
|
||||
"adf-class-name": true,
|
||||
"adf-no-on-prefix-output-name": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Supported Rules
|
||||
-----
|
||||
|
||||
Rule Name | Description |
|
||||
---------- | ------------ |
|
||||
`adf-file-name` | The name of the File should not start with ADF Alfresco or Activiti prefix |
|
||||
`adf-class-name` | The name of the class should not start with ADF Alfresco or Activiti prefix |
|
||||
`adf-no-on-prefix-output-name` | Angular allows for an alternative syntax on-*. If the event itself was prefixed with on this would result in an on-onEvent binding expression |
|
||||
|
|
44
tools/tslint-rules/adfClassNameRule.js
Normal file
44
tools/tslint-rules/adfClassNameRule.js
Normal file
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const Lint = require("tslint");
|
||||
const sprintf_js_1 = require("sprintf-js");
|
||||
const walkerFactory_1 = require("codelyzer/walkerFactory/walkerFactory");
|
||||
const walkerFn_1 = require("codelyzer/walkerFactory/walkerFn");
|
||||
const function_1 = require("codelyzer/util/function");
|
||||
class Rule extends Lint.Rules.AbstractRule {
|
||||
static invalidName(className) {
|
||||
var whiteList = ['ActivitiContentComponent', 'ActivitiForm'];
|
||||
var classNameReg = /^(alfresco|activiti|adf|activity)/ig;
|
||||
var classNameMatch = classNameReg.exec(className);
|
||||
var isWhiteListName = whiteList.find((currentWhiteListName) => {
|
||||
return currentWhiteListName === className;
|
||||
});
|
||||
if (classNameMatch && !isWhiteListName) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
apply(sourceFile) {
|
||||
return this.applyWithWalker(Rule.walkerBuilder(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
Rule.metadata = {
|
||||
ruleName: 'adf-class-name',
|
||||
type: 'maintainability',
|
||||
description: `Enforce consistent name avoid prefix`,
|
||||
descriptionDetails: `See more at https://angular.io/styleguide#style-05-13.`,
|
||||
rationale: `Consistent conventions make it easy to quickly identify class when you search with autocomplete.`,
|
||||
options: null,
|
||||
optionsDescription: "Not configurable.",
|
||||
typescriptOnly: true,
|
||||
};
|
||||
Rule.FAILURE_STRING = 'The name of the class should not start with ADF Alfresco or Activiti prefix ';
|
||||
Rule.walkerBuilder = walkerFn_1.all(walkerFn_1.validateComponent((meta, suffixList) => function_1.Maybe.lift(meta.controller)
|
||||
.fmap(controller => controller.name)
|
||||
.fmap(name => {
|
||||
const className = name.text;
|
||||
if (Rule.invalidName(className)) {
|
||||
return [new walkerFactory_1.Failure(name, sprintf_js_1.sprintf(Rule.FAILURE_STRING + className, className, suffixList))];
|
||||
}
|
||||
})));
|
||||
exports.Rule = Rule;
|
61
tools/tslint-rules/adfClassNameRule.ts
Normal file
61
tools/tslint-rules/adfClassNameRule.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import * as Lint from 'tslint';
|
||||
import * as ts from 'typescript';
|
||||
import { sprintf } from 'sprintf-js';
|
||||
import { ComponentMetadata } from 'codelyzer/angular/metadata';
|
||||
import { Failure } from 'codelyzer/walkerFactory/walkerFactory';
|
||||
import { all, validateComponent } from 'codelyzer/walkerFactory/walkerFn';
|
||||
import { Maybe, F2 } from 'codelyzer/util/function';
|
||||
import { IOptions } from 'tslint';
|
||||
import { NgWalker } from 'codelyzer/angular/ngWalker';
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
|
||||
public static metadata: Lint.IRuleMetadata = {
|
||||
ruleName: 'adf-class-name',
|
||||
type: 'maintainability',
|
||||
description: `Enforce consistent name avoid prefix`,
|
||||
descriptionDetails: `See more at https://angular.io/styleguide#style-05-13.`,
|
||||
rationale: `Consistent conventions make it easy to quickly identify class when you search with autocomplete.`,
|
||||
options: null,
|
||||
optionsDescription: "Not configurable.",
|
||||
typescriptOnly: true,
|
||||
};
|
||||
|
||||
public static FAILURE_STRING = 'The name of the class should not start with ADF Alfresco or Activiti prefix ';
|
||||
|
||||
static walkerBuilder: F2<ts.SourceFile, IOptions, NgWalker> =
|
||||
all(
|
||||
validateComponent((meta: ComponentMetadata, suffixList?: string[]) =>
|
||||
Maybe.lift(meta.controller)
|
||||
.fmap(controller => controller.name)
|
||||
.fmap(name => {
|
||||
const className = name.text;
|
||||
if (Rule.invalidName(className)) {
|
||||
return [new Failure(name, sprintf(Rule.FAILURE_STRING + className, className, suffixList))];
|
||||
}
|
||||
})
|
||||
));
|
||||
|
||||
static invalidName(className: string): boolean {
|
||||
var whiteList = ['ActivitiContentComponent', 'ActivitiForm'];
|
||||
|
||||
var classNameReg = /^(alfresco|activiti|adf|activity)/ig;
|
||||
var classNameMatch = classNameReg.exec(className);
|
||||
|
||||
var isWhiteListName = whiteList.find((currentWhiteListName) => {
|
||||
return currentWhiteListName === className;
|
||||
});
|
||||
|
||||
if (classNameMatch && !isWhiteListName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(
|
||||
Rule.walkerBuilder(sourceFile, this.getOptions())
|
||||
);
|
||||
}
|
||||
}
|
44
tools/tslint-rules/adfFileNameRule.js
Normal file
44
tools/tslint-rules/adfFileNameRule.js
Normal file
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const Lint = require("tslint");
|
||||
class Rule extends Lint.Rules.AbstractRule {
|
||||
apply(sourceFile) {
|
||||
return this.applyWithWalker(new AdfFileName(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
Rule.metadata = {
|
||||
ruleName: 'adf-file-name',
|
||||
type: 'maintainability',
|
||||
description: `Enforce consistent name avoid prefix`,
|
||||
descriptionDetails: `See more at https://angular.io/styleguide#style-05-13.`,
|
||||
rationale: `Consistent conventions make it easy to quickly identify files when you search with autocomplete.`,
|
||||
options: null,
|
||||
optionsDescription: "Not configurable.",
|
||||
typescriptOnly: true,
|
||||
};
|
||||
Rule.FAILURE_STRING = 'The name of the File should not start with ADF Alfresco or Activiti prefix ';
|
||||
exports.Rule = Rule;
|
||||
class AdfFileName extends Lint.RuleWalker {
|
||||
visitSourceFile(node) {
|
||||
var whiteList = ['activiti-alfresco.service.ts', 'activiti-alfresco.service.spec.ts',
|
||||
'alfresco-api.service.ts', 'alfresco-api.service.spects'];
|
||||
var fileName = this.getFilename();
|
||||
var fileNameReg = /^(alfresco|activiti|adf|activity)/ig;
|
||||
var filenameMatch = fileNameReg.exec(fileName);
|
||||
var isWhiteListName = whiteList.find((currentWhiteListName) => {
|
||||
return currentWhiteListName === fileName;
|
||||
});
|
||||
if (filenameMatch && !isWhiteListName) {
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING + fileName));
|
||||
super.visitSourceFile(node);
|
||||
}
|
||||
}
|
||||
getFilename() {
|
||||
const filename = this.getSourceFile().fileName;
|
||||
const lastSlash = filename.lastIndexOf('/');
|
||||
if (lastSlash > -1) {
|
||||
return filename.substring(lastSlash + 1);
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
}
|
53
tools/tslint-rules/adfFileNameRule.ts
Normal file
53
tools/tslint-rules/adfFileNameRule.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import * as ts from "typescript";
|
||||
import * as Lint from "tslint";
|
||||
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static metadata: Lint.IRuleMetadata = {
|
||||
ruleName: 'adf-file-name',
|
||||
type: 'maintainability',
|
||||
description: `Enforce consistent name avoid prefix`,
|
||||
descriptionDetails: `See more at https://angular.io/styleguide#style-05-13.`,
|
||||
rationale: `Consistent conventions make it easy to quickly identify files when you search with autocomplete.`,
|
||||
options: null,
|
||||
optionsDescription: "Not configurable.",
|
||||
typescriptOnly: true,
|
||||
};
|
||||
|
||||
public static FAILURE_STRING = 'The name of the File should not start with ADF Alfresco or Activiti prefix ';
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(new AdfFileName(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
// The walker takes care of all the work.
|
||||
class AdfFileName extends Lint.RuleWalker {
|
||||
public visitSourceFile(node: ts.SourceFile) {
|
||||
var whiteList = ['activiti-alfresco.service.ts', 'activiti-alfresco.service.spec.ts',
|
||||
'alfresco-api.service.ts', 'alfresco-api.service.spects'];
|
||||
|
||||
var fileName = this.getFilename();
|
||||
|
||||
var fileNameReg = /^(alfresco|activiti|adf|activity)/ig;
|
||||
var filenameMatch = fileNameReg.exec(fileName);
|
||||
|
||||
var isWhiteListName = whiteList.find((currentWhiteListName) => {
|
||||
return currentWhiteListName === fileName;
|
||||
});
|
||||
|
||||
if (filenameMatch && !isWhiteListName) {
|
||||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING + fileName));
|
||||
super.visitSourceFile(node);
|
||||
}
|
||||
}
|
||||
|
||||
private getFilename(): string {
|
||||
const filename = this.getSourceFile().fileName;
|
||||
const lastSlash = filename.lastIndexOf('/');
|
||||
if (lastSlash > -1) {
|
||||
return filename.substring(lastSlash + 1);
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
}
|
34
tools/tslint-rules/adfPrefixNameRule.js
Normal file
34
tools/tslint-rules/adfPrefixNameRule.js
Normal file
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const Lint = require("tslint");
|
||||
const sprintf_js_1 = require("sprintf-js");
|
||||
const ngWalker_1 = require("codelyzer/angular/ngWalker");
|
||||
class Rule extends Lint.Rules.AbstractRule {
|
||||
apply(sourceFile) {
|
||||
return this.applyWithWalker(new ADFOutputPrefixNameRule(sourceFile, this.getOptions()));
|
||||
}
|
||||
}
|
||||
Rule.metadata = {
|
||||
ruleName: 'adf-prefix-name',
|
||||
type: 'maintainability',
|
||||
description: `Name events without the prefix on`,
|
||||
descriptionDetails: `See more at https://angular.io/guide/styleguide#dont-prefix-output-properties`,
|
||||
rationale: `Angular allows for an alternative syntax on-*. If the event itself was prefixed with on this would result in an on-onEvent binding expression`,
|
||||
options: null,
|
||||
optionsDescription: `Not configurable.`,
|
||||
typescriptOnly: true,
|
||||
};
|
||||
Rule.FAILURE_STRING = 'In the class "%s", the output ' +
|
||||
'property "%s" should not be prefixed with on';
|
||||
exports.Rule = Rule;
|
||||
class ADFOutputPrefixNameRule extends ngWalker_1.NgWalker {
|
||||
visitNgOutput(property, output, args) {
|
||||
let className = property.parent.name.text;
|
||||
let memberName = property.name.text;
|
||||
if (memberName && memberName.startsWith('on')) {
|
||||
let failureConfig = [className, memberName];
|
||||
failureConfig.unshift(Rule.FAILURE_STRING);
|
||||
this.addFailure(this.createFailure(property.getStart(), property.getWidth(), sprintf_js_1.sprintf.apply(this, failureConfig)));
|
||||
}
|
||||
}
|
||||
}
|
43
tools/tslint-rules/adfPrefixNameRule.ts
Normal file
43
tools/tslint-rules/adfPrefixNameRule.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import * as Lint from 'tslint';
|
||||
import * as ts from 'typescript';
|
||||
import { sprintf } from 'sprintf-js';
|
||||
import { NgWalker } from 'codelyzer/angular/ngWalker';
|
||||
|
||||
export class Rule extends Lint.Rules.AbstractRule {
|
||||
public static metadata: Lint.IRuleMetadata = {
|
||||
ruleName: 'adf-prefix-name',
|
||||
type: 'maintainability',
|
||||
description: `Name events without the prefix on`,
|
||||
descriptionDetails: `See more at https://angular.io/guide/styleguide#dont-prefix-output-properties`,
|
||||
rationale: `Angular allows for an alternative syntax on-*. If the event itself was prefixed with on this would result in an on-onEvent binding expression`,
|
||||
options: null,
|
||||
optionsDescription: `Not configurable.`,
|
||||
typescriptOnly: true,
|
||||
};
|
||||
|
||||
static FAILURE_STRING: string = 'In the class "%s", the output ' +
|
||||
'property "%s" should not be prefixed with on';
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
||||
return this.applyWithWalker(
|
||||
new ADFOutputPrefixNameRule(sourceFile,
|
||||
this.getOptions()));
|
||||
}
|
||||
}
|
||||
|
||||
class ADFOutputPrefixNameRule extends NgWalker {
|
||||
visitNgOutput(property: ts.PropertyDeclaration, output: ts.Decorator, args: string[]) {
|
||||
let className = (<any>property).parent.name.text;
|
||||
let memberName = (<any>property.name).text;
|
||||
|
||||
if (memberName && memberName.startsWith('on')) {
|
||||
let failureConfig: string[] = [className, memberName];
|
||||
failureConfig.unshift(Rule.FAILURE_STRING);
|
||||
this.addFailure(
|
||||
this.createFailure(
|
||||
property.getStart(),
|
||||
property.getWidth(),
|
||||
sprintf.apply(this, failureConfig)));
|
||||
}
|
||||
}
|
||||
}
|
8
tools/tslint-rules/index.js
Normal file
8
tools/tslint-rules/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var adfClassNameRule_1 = require("./adfClassNameRule");
|
||||
exports.ADFClassNameRule = adfClassNameRule_1.Rule;
|
||||
var adfFileNameRule_1 = require("./adfFileNameRule");
|
||||
exports.ADFComponentSelectorRule = adfFileNameRule_1.Rule;
|
||||
var adfPrefixNameRule_1 = require("./adfPrefixNameRule");
|
||||
exports.ADFOutputPrefixNameRule = adfPrefixNameRule_1.Rule;
|
3
tools/tslint-rules/index.ts
Normal file
3
tools/tslint-rules/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export { Rule as ADFClassNameRule } from './adfClassNameRule';
|
||||
export { Rule as ADFComponentSelectorRule } from './adfFileNameRule';
|
||||
export { Rule as ADFOutputPrefixNameRule } from './adfPrefixNameRule';
|
2179
tools/tslint-rules/package-lock.json
generated
Normal file
2179
tools/tslint-rules/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
56
tools/tslint-rules/package.json
Normal file
56
tools/tslint-rules/package.json
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "adf-tslint-rules",
|
||||
"description": "Custom Rules for the ADF project",
|
||||
"version": "0.0.4",
|
||||
"author": "Alfresco Software, Ltd.",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"tscv": "tsc --version",
|
||||
"tsc": "tsc",
|
||||
"tsc:watch": "tsc --w"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Eugenio Romano",
|
||||
"email": "eugenio.romano@alfresco.com"
|
||||
}
|
||||
],
|
||||
"devDependencies": {
|
||||
"@angular/compiler": "4.2.3",
|
||||
"@angular/core": "4.2.3",
|
||||
"@types/chai": "3.4.33",
|
||||
"@types/less": "0.0.31",
|
||||
"@types/mocha": "2.2.32",
|
||||
"@types/node": "6.0.41",
|
||||
"@types/node-sass": "3.10.31",
|
||||
"@types/source-map": "0.5.0",
|
||||
"@types/sprintf-js": "0.0.27",
|
||||
"chai": "3.5.0",
|
||||
"chai-spies": "0.7.1",
|
||||
"minimalist": "1.0.0",
|
||||
"mocha": "3.0.2",
|
||||
"node-sass": "3.13.0",
|
||||
"rimraf": "2.5.2",
|
||||
"rxjs": "5.4.1",
|
||||
"ts-node": "1.2.2",
|
||||
"tslint": "5.0.0",
|
||||
"typescript": "2.4.0",
|
||||
"zone.js": "0.8.4",
|
||||
"js-yaml": "3.8.4",
|
||||
"json-stringify-pretty-compact": "1.0.4",
|
||||
"@types/js-yaml": "3.5.31"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tslint": "5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"app-root-path": "2.0.1",
|
||||
"css-selector-tokenizer": "0.7.0",
|
||||
"cssauron": "1.4.0",
|
||||
"semver-dsl": "1.0.1",
|
||||
"source-map": "0.5.6",
|
||||
"sprintf-js": "1.0.3",
|
||||
"codelyzer": "3.1.2"
|
||||
},
|
||||
"license": "Apache-2.0"
|
||||
}
|
22
tools/tslint-rules/tsconfig.json
Normal file
22
tools/tslint-rules/tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"declaration": false,
|
||||
"noImplicitAny": false,
|
||||
"removeComments": true,
|
||||
"lib": ["es6", "es2015", "dom"],
|
||||
"noLib": false,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules"
|
||||
],
|
||||
"types": [
|
||||
"mocha",
|
||||
"chai",
|
||||
"node",
|
||||
"sprintf-js"
|
||||
]
|
||||
}
|
||||
}
|
5
tools/tslint-rules/tslint.json
Normal file
5
tools/tslint-rules/tslint.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"rules": {
|
||||
"adf-file-naming": true
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user