From e0afb0768ba8353ab2958b357bc1026070842b7b Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 10 Aug 2019 04:56:59 +0200 Subject: [PATCH 1/2] add php parser --- .gitignore | 1 + package-lock.json | 36 ++ package.json | 14 +- src/ClassInfo.ts | 22 ++ src/Location.ts | 12 + src/ParsedResult.ts | 5 + src/Parser.ts | 157 ++++++++ src/Resolver.ts | 565 +++++++++++++++++++++++++++++ src/{classes.js => classes.ts} | 2 +- src/{extension.js => extension.ts} | 16 +- tsconfig.json | 21 ++ tslint.json | 15 + 12 files changed, 850 insertions(+), 16 deletions(-) create mode 100644 package-lock.json create mode 100644 src/ClassInfo.ts create mode 100644 src/Location.ts create mode 100644 src/ParsedResult.ts create mode 100644 src/Parser.ts create mode 100644 src/Resolver.ts rename src/{classes.js => classes.ts} (99%) rename src/{extension.js => extension.ts} (84%) create mode 100644 tsconfig.json create mode 100644 tslint.json diff --git a/.gitignore b/.gitignore index 3c3629e..2f06a56 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +out/* diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ce010d5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,36 @@ +{ + "name": "php-namespace-resolver", + "version": "1.1.8", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "8.10.51", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.51.tgz", + "integrity": "sha512-cArrlJp3Yv6IyFT/DYe+rlO8o3SIHraALbBW/+CcCYW/a9QucpLI+n2p4sRxAvl2O35TiecpX2heSZtJjvEO+Q==", + "dev": true + }, + "@types/vscode": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.36.0.tgz", + "integrity": "sha512-SbHR3Q5g/C3N+Ila3KrRf1rSZiyHxWdOZ7X3yFHXzw6HrvRLuVZrxnwEX0lTBMRpH9LkwZdqRTgXW+D075jxkg==", + "dev": true + }, + "node-natural-sort": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/node-natural-sort/-/node-natural-sort-0.8.7.tgz", + "integrity": "sha512-rMaLlHV5BlnRhIl6jUfgqdLY5U0NJkIxUdOsmpz3Txwh7js4+GwTiomhO8W4rp3SvX1zZ56mx13zfEWESr+qqA==" + }, + "php-parser": { + "version": "3.0.0-prerelease.8", + "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.0.0-prerelease.8.tgz", + "integrity": "sha512-sVMPsnPd3q7kf1vs0VUROo71Klcs6s7Ho5TSMcBcI8Qg5VuVMaM5far36E4qaYTH8SW+2Tquv5RuU7e8+jfjIw==" + }, + "typescript": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", + "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", + "dev": true + } + } +} diff --git a/package.json b/package.json index 50559c4..b9b635d 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "author": "Mehedi Hassan ", "license": "SEE LICENSE IN LICENSE", "engines": { - "vscode": "^1.15.0" + "vscode": "^1.34.0" }, "categories": [ "Other" @@ -33,7 +33,7 @@ "onCommand:namespaceResolver.highlightNotUsed", "onCommand:namespaceResolver.generateNamespace" ], - "main": "./src/extension", + "main": "./out/extension.js", "icon": "images/icon.png", "contributes": { "menus": { @@ -208,13 +208,13 @@ "bugs": { "url": "https://github.com/MehediDracula/PHP-Namespace-Resolver/issues" }, - "scripts": { - "postinstall": "node ./node_modules/vscode/bin/install" - }, "devDependencies": { - "vscode": "^1.0.0" + "@types/node": "^8.10.25", + "@types/vscode": "^1.34.0", + "typescript": "^3.5.1" }, "dependencies": { - "node-natural-sort": "^0.8.6" + "node-natural-sort": "^0.8.6", + "php-parser": "^3.0.0-prerelease.8" } } diff --git a/src/ClassInfo.ts b/src/ClassInfo.ts new file mode 100644 index 0000000..f77d3d0 --- /dev/null +++ b/src/ClassInfo.ts @@ -0,0 +1,22 @@ +import { Position } from 'vscode'; +import { Location } from './Location'; +export class ClassInfo { + public name: string; + public location: Location; + constructor(parsedClassObject: any) { + this.name = parsedClassObject.name; + this.location = parsedClassObject.loc; + } + get startPosition(): Position { + return new Position(this.location.start.line - 1, this.location.start.column); + } + get endPosition(): Position { + return new Position(this.location.end.line - 1, this.location.end.column); + } + get baseName(): string { + return this.name.split('\\').pop(); + } + public hasSameBaseName(classInfo: ClassInfo): boolean { + return this.baseName === classInfo.baseName; + } +} diff --git a/src/Location.ts b/src/Location.ts new file mode 100644 index 0000000..bb9dc7b --- /dev/null +++ b/src/Location.ts @@ -0,0 +1,12 @@ +export type Location = { + start: { + line: number; + column: number; + offset: number; + }; + end: { + line: number; + column: number; + offset: number; + }; +}; diff --git a/src/ParsedResult.ts b/src/ParsedResult.ts new file mode 100644 index 0000000..08249e8 --- /dev/null +++ b/src/ParsedResult.ts @@ -0,0 +1,5 @@ +import { ClassInfo } from "./ClassInfo"; +export type ParsedResult = { + useStatements: ClassInfo[]; + classesUsed: ClassInfo[]; +}; diff --git a/src/Parser.ts b/src/Parser.ts new file mode 100644 index 0000000..58afac9 --- /dev/null +++ b/src/Parser.ts @@ -0,0 +1,157 @@ +import phpParser from 'php-parser'; +import { ParsedResult } from './ParsedResult'; +import { ClassInfo } from './ClassInfo'; + + +export class Parser { + private text: string; + private parser: any; + public constructor(text: string) { + this.text = text; + + this.parser = new phpParser({ + parser: { + extractDoc: false, + php7: true + }, + ast: { + withPositions: true + } + }); + } + + public parse(): ParsedResult { + return this.getClasses(); + } + + private getClasses(): ParsedResult { + let parsedCode = this.parser.parseCode(this.text, ''); + + return { + useStatements: this.getUseStatements(parsedCode), + classesUsed: this.getClassesInBody(parsedCode) + }; + } + + private getClassesInBody(parsedCode: object): ClassInfo[] { + let allClasses = []; + this.getBodyElements(parsedCode).forEach(row => { + if (this.isObject(row)) { + allClasses.push(...this.getClassesForObject(row)); + } + }); + + allClasses = this.filterOutFunctions(allClasses); + + return allClasses.concat(this.getExtendedClasses(parsedCode)); + } + + private getExtendedClasses(parsedCode: any): ClassInfo[] { + + const classBody = this.getClass(parsedCode); + if (!classBody) { + return []; + } + const classes = []; + + if ((classBody.extends)) { + classes.push(new ClassInfo(classBody.extends)); + } + + if (Array.isArray(classBody.implements)) { + classes.push(...classBody.implements.map(row => { + return new ClassInfo(row); + })); + } + return classes; + } + + private filterOutFunctions(classes: ClassInfo[]): ClassInfo[] { + return classes.filter(row => { + const charAfterClass = this.text.substring(row.location.end.offset, row.location.end.offset + 1); + if (charAfterClass === '(') { + const charsBeforeClass = this.text.substring(row.location.start.offset - 4, row.location.start.offset); + if (charsBeforeClass !== 'new ') { + return false; + } + } + return true; + }); + } + + private getClassesForObject(row: Record): ClassInfo[] { + const classes: ClassInfo[] = []; + + Object.entries(row).forEach(([key, value]) => { + if (key === 'kind' && value === 'classreference') { + classes.push(new ClassInfo(row)); + } else if (Array.isArray(value)) { + value.forEach(row => { + if (this.isObject(row)) { + classes.push(...this.getClassesForObject(row)); + } + }); + } else if (this.isObject(value)) { + classes.push(...this.getClassesForObject(value)); + } + }); + return classes; + } + + private isObject(value: any) { + if (value === null) { + return false; + } + + return typeof value === 'object'; + } + + private getElements(parsedCode: any): any[] { + let children = parsedCode.children; + + const nameSpaceObject = children.find(row => { + return row.kind === 'namespace'; + }); + if (nameSpaceObject) { + return nameSpaceObject.children; + } + return children; + } + + private getClass(parsedCode: object): any | null { + const bodyType = this.getElements(parsedCode).find(row => { + return row.kind === 'class'; + }); + + return bodyType; + } + + private getBodyElements(parsedCode: any): any[] { + const classObject = this.getClass(parsedCode); + + if (classObject) { + return classObject.body; + } + + const returnType = parsedCode.children.find(row => { + return row.kind === 'return'; + }); + + if (returnType) { + return returnType.expr.items; + } + return []; + } + + private getUseStatements(parsedCode: object): ClassInfo[] { + return this.getElements(parsedCode).flatMap(child => { + if (child.kind === 'usegroup') { + return child.items.map(item => { + return new ClassInfo(item); + }); + } + return []; + }); + } + +} diff --git a/src/Resolver.ts b/src/Resolver.ts new file mode 100644 index 0000000..0914a5e --- /dev/null +++ b/src/Resolver.ts @@ -0,0 +1,565 @@ +import { Parser } from './Parser'; +import { ClassInfo } from "./ClassInfo"; +import { ParsedResult } from "./ParsedResult"; + +import builtInClasses from './classes'; +import { naturalSort } from 'node-natural-sort'; +import { window, workspace, TextEditor, Range, Position, Selection, TextEditorDecorationType } from 'vscode'; + + +export class Resolver { + private decorationTypeForNotImported: TextEditorDecorationType; + private decorationTypeForNotUsed: TextEditorDecorationType; + constructor() { + this.decorationTypeForNotImported = window.createTextEditorDecorationType({ + backgroundColor: 'rgba(255,155,0, 0.5)', + light: { + borderColor: 'darkblue' + }, + dark: { + borderColor: 'lightblue' + } + }); + + this.decorationTypeForNotUsed = window.createTextEditorDecorationType({ + backgroundColor: 'rgba(255,55,55, 0.5)', + light: { + borderColor: 'darkblue' + }, + dark: { + borderColor: 'lightblue' + } + }); + } + + async importCommand(selection: any) { + let resolving = this.resolving(selection); + + if (resolving === undefined) { + return this.showErrorMessage(`$(issue-opened) No class is selected.`); + } + + let fqcn; + let replaceClassAfterImport = false; + + if (/\\/.test(resolving)) { + fqcn = resolving; + replaceClassAfterImport = true; + } else { + let files = await this.findFiles(resolving); + let namespaces = await this.findNamespaces(resolving, files); + + fqcn = await this.pickClass(namespaces); + } + + this.importClass(selection, fqcn, replaceClassAfterImport); + } + + async importAll() { + let text = this.activeEditor().document.getText(); + var result = this.parseText(text); + + let notImported = this.getNotImported(result); + + for (let phpClass of notImported) { + await this.importCommand(phpClass.name); + } + } + + parseText(text) { + return (new Parser(text)).parse();; + } + + getNotImported(result: ParsedResult): ClassInfo[] { + return result.classesUsed.filter(function (phpClass) { + return !result.useStatements.some(useStatement => { + return useStatement.hasSameBaseName(phpClass); + }); + }); + } + + async highlightNotImported() { + let text = this.activeEditor().document.getText(); + + var result = this.parseText(text); + + let notImported = this.getNotImported(result); + + // Highlight diff + const decorationOptions = notImported.map(classObject => { + return { + range: new Range( + classObject.startPosition, + classObject.endPosition + ), + hoverMessage: `Class '${classObject.name}' is not imported.`, + }; + }); + + + + this.activeEditor().setDecorations(this.decorationTypeForNotImported, decorationOptions); + } + + async highlightNotUsed() { + const text = this.activeEditor().document.getText(); + + var parsed = this.parseText(text); + + let notUsed = parsed.useStatements.filter(function (useStatement) { + return !parsed.classesUsed.some(phpClass => { + return useStatement.hasSameBaseName(phpClass); + }); + }); + + const decorationOptions = notUsed.map(row => { + return { + range: new Range(row.startPosition, row.endPosition), + hoverMessage: `Class '${row.name}' is not used.`, + }; + }); + + + this.activeEditor().setDecorations(this.decorationTypeForNotUsed, decorationOptions); + } + + importClass(selection, fqcn, replaceClassAfterImport = false) { + let useStatements, declarationLines; + + try { + [useStatements, declarationLines] = this.getDeclarations(fqcn); + } catch (error) { + return this.showErrorMessage(error.message); + } + + let classBaseName = fqcn.match(/(\w+)/g).pop(); + + if (this.hasConflict(useStatements, classBaseName)) { + this.insertAsAlias(selection, fqcn, useStatements, declarationLines); + } else if (replaceClassAfterImport) { + this.importAndReplaceSelectedClass(selection, classBaseName, fqcn, declarationLines); + } else { + this.insert(fqcn, declarationLines); + } + } + + async insert(fqcn, declarationLines, alias = null) { + let [prepend, append, insertLine] = this.getInsertLine(declarationLines); + + await this.activeEditor().edit(textEdit => { + textEdit.replace( + new Position((insertLine), 0), + (`${prepend}use ${fqcn}`) + (alias !== null ? ` as ${alias}` : '') + (`;${append}`) + ); + }); + + if (this.config('autoSort')) { + this.sortImports(); + } + + this.showMessage('$(check) The class is imported.'); + } + + async insertAsAlias(selection, fqcn, useStatements, declarationLines) { + let alias = await window.showInputBox({ + placeHolder: 'Enter an alias or leave it empty to replace' + }); + + if (alias === undefined) { + return; + } + + if (this.hasConflict(useStatements, alias)) { + this.showErrorMessage(`$(issue-opened) This alias is already in use.`); + + this.insertAsAlias(selection, fqcn, useStatements, declarationLines) + } else if (alias !== '') { + this.importAndReplaceSelectedClass(selection, alias, fqcn, declarationLines, alias); + } else if (alias === '') { + this.replaceUseStatement(fqcn, useStatements); + } + } + + async replaceUseStatement(fqcn, useStatements) { + let useStatement = useStatements.find(use => { + let className = use.text.match(/(\w+)?;/).pop(); + + return fqcn.endsWith(className); + }); + + await this.activeEditor().edit(textEdit => { + textEdit.replace( + new Range(useStatement.line, 0, useStatement.line, useStatement.text.length), + `use ${fqcn};` + ); + }); + + if (this.config('autoSort')) { + this.sortImports(); + } + } + + async replaceNamespaceStatement(namespace, line) { + let realLine = line - 1; + let text = this.activeEditor().document.lineAt(realLine).text; + let newNs = text.replace(/namespace (.+)/, namespace); + + await this.activeEditor().edit(textEdit => { + textEdit.replace( + new Range(realLine, 0, realLine, text.length), + newNs.trim() + ); + }); + } + + async importAndReplaceSelectedClass(selection, replacingClassName, fqcn, declarationLines, alias = null) { + await this.changeSelectedClass(selection, replacingClassName, false); + + this.insert(fqcn, declarationLines, alias); + } + + async expandCommand(selection) { + let resolving = this.resolving(selection); + + if (resolving === null) { + return this.showErrorMessage(`$(issue-opened) No class is selected.`); + } + + let files = await this.findFiles(resolving); + let namespaces = await this.findNamespaces(resolving, files); + let fqcn = await this.pickClass(namespaces); + + this.changeSelectedClass(selection, fqcn, true); + } + + async changeSelectedClass(selection, fqcn, prependBackslash = false) { + await this.activeEditor().edit(textEdit => { + textEdit.replace( + this.activeEditor().document.getWordRangeAtPosition(selection.active), + (prependBackslash && this.config('leadingSeparator') ? '\\' : '') + fqcn + ); + }); + + let newPosition = new Position(selection.active.line, selection.active.character); + + this.activeEditor().selection = new Selection(newPosition, newPosition); + } + + sortCommand() { + try { + this.sortImports(); + } catch (error) { + return this.showErrorMessage(error.message); + } + + this.showMessage('$(check) Imports are sorted.'); + } + + findFiles(resolving) { + return workspace.findFiles(`**/${resolving}.php`, this.config('exclude') as string); + } + + findNamespaces(resolving, files) { + return new Promise((resolve, reject) => { + let textDocuments = this.getTextDocuments(files, resolving); + + Promise.all(textDocuments).then(docs => { + let parsedNamespaces = this.parseNamespaces(docs, resolving); + + if (parsedNamespaces.length === 0) { + return this.showErrorMessage(`$(circle-slash) The class '${resolving}' is not found.`); + } + + resolve(parsedNamespaces); + }); + }); + } + + pickClass(namespaces) { + return new Promise((resolve, reject) => { + if (namespaces.length === 1) { + // Only one namespace found so no need to show picker. + return resolve(namespaces[0]); + } + + window.showQuickPick(namespaces).then(picked => { + if (picked !== undefined) { + resolve(picked); + } + }); + }) + } + + getTextDocuments(files, resolving) { + let textDocuments = []; + + for (let i = 0; i < files.length; i++) { + let fileName = files[i].fsPath.replace(/^.*[\\\/]/, '').split('.')[0]; + + if (fileName !== resolving) { + continue; + } + + textDocuments.push(workspace.openTextDocument(files[i])); + } + + return textDocuments; + } + + parseNamespaces(docs, resolving) { + let parsedNamespaces = []; + + for (let i = 0; i < docs.length; i++) { + for (let line = 0; line < docs[i].lineCount; line++) { + let textLine = docs[i].lineAt(line).text; + + if (textLine.startsWith('namespace ') || textLine.startsWith(' 0) { + parsedNamespaces.push(resolving); + } + + return parsedNamespaces; + } + + sortImports() { + let [useStatements,] = this.getDeclarations(); + + if ((useStatements as any[]).length <= 1) { + throw new Error('$(issue-opened) Nothing to sort.'); + } + + let sortFunction = (a, b) => { + if (this.config('sortAlphabetically')) { + if (a.text.toLowerCase() < b.text.toLowerCase()) return -1; + if (a.text.toLowerCase() > b.text.toLowerCase()) return 1; + return 0; + } else { + if (a.text.length == b.text.length) { + if (a.text.toLowerCase() < b.text.toLowerCase()) return -1; + if (a.text.toLowerCase() > b.text.toLowerCase()) return 1; + } + + return a.text.length - b.text.length; + } + } + + if (this.config('sortNatural')) { + let natsort = naturalSort({ + caseSensitive: true, + order: this.config('sortAlphabetically') ? 'ASC' : 'DESC' + }); + + sortFunction = (a, b) => { + return natsort(a.text, b.text); + }; + } + + let sorted = (useStatements as any[]).slice().sort(sortFunction); + + this.activeEditor().edit(textEdit => { + for (let i = 0; i < sorted.length; i++) { + textEdit.replace( + new Range(useStatements[i].line, 0, useStatements[i].line, useStatements[i].text.length), + sorted[i].text + ); + } + }); + } + + activeEditor() { + return window.activeTextEditor as TextEditor; + } + + hasConflict(useStatements, resolving) { + for (let i = 0; i < useStatements.length; i++) { + if (useStatements[i].text.match(/(\w+)?;/).pop() === resolving) { + return true; + } + } + + return false; + } + + getDeclarations(pickedClass = null) { + let useStatements = []; + let declarationLines = { + PHPTag: 0, + namespace: null, + useStatement: null, + class: null + }; + + for (let line = 0; line < this.activeEditor().document.lineCount; line++) { + let text = this.activeEditor().document.lineAt(line).text; + + if (pickedClass !== null && text === `use ${pickedClass};`) { + throw new Error('$(issue-opened) The class is already imported.'); + } + + // break if all declarations were found. + if (declarationLines.PHPTag && declarationLines.namespace && + declarationLines.useStatement && declarationLines.class) { + break; + } + + if (text.startsWith(' { + let composerJson = JSON.parse(document.getText()); + let psr4 = (composerJson.autoload || {})['psr-4']; + + if (psr4 === undefined) { + return this.showErrorMessage('No psr-4 key in composer.json autoload object, automatic namespace generation failed'); + } + + let devPsr4 = (composerJson['autoload-dev'] || {})['psr-4']; + + if (devPsr4 !== undefined) { + psr4 = {...psr4, ...devPsr4}; + } + + let namespaceBase = Object.keys(psr4).filter(function (namespaceBase) { + return currentPath.split(psr4[namespaceBase])[1]; + }).concat(Object.keys(psr4))[0]; + + let baseDir = psr4[namespaceBase]; + + namespaceBase = namespaceBase.replace(/\\$/, ''); + + let namespaceList = currentPath.split(baseDir); + let namespace: string = null; + if (namespaceList[1]) { + namespace = namespaceList[1] + namespace = namespace.replace(/\//g, '\\'); + namespace = namespace.replace(/^\\/, ''); + namespace = namespaceBase + '\\' + namespace; + } else { + namespace = namespaceBase; + } + + namespace = 'namespace ' + namespace + ';' + "\n" + + let declarationLines; + + try { + [, declarationLines] = this.getDeclarations(); + } catch (error) { + return this.showErrorMessage(error.message); + } + + if (declarationLines.namespace !== null) { + this.replaceNamespaceStatement(namespace, declarationLines.namespace); + } else { + this.activeEditor().edit(textEdit => { + textEdit.insert(new Position(1, 0), namespace); + }); + } + }); + } +} diff --git a/src/classes.js b/src/classes.ts similarity index 99% rename from src/classes.js rename to src/classes.ts index 2c1f604..1bb9195 100644 --- a/src/classes.js +++ b/src/classes.ts @@ -1,4 +1,4 @@ -module.exports = [ +export default [ "stdClass", "Exception", "ErrorException", diff --git a/src/extension.js b/src/extension.ts similarity index 84% rename from src/extension.js rename to src/extension.ts index d04e6fe..79e61e5 100644 --- a/src/extension.js +++ b/src/extension.ts @@ -1,22 +1,23 @@ -let vscode = require('vscode'); -let Resolver = require('./Resolver'); - -function activate(context) { +/* let vscode = require('vscode'); +let Resolver = require('./Resolver'); */ +import * as vscode from 'vscode'; +import { Resolver } from './Resolver'; +export function activate(context: { subscriptions: any }) { let resolver = new Resolver; context.subscriptions.push( vscode.commands.registerCommand('namespaceResolver.import', async () => { - let selections = vscode.window.activeTextEditor.selections; + let selections = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.selections : []; for (let i = 0; i < selections.length; i++) { await resolver.importCommand(selections[i]); } }) - ); + ) context.subscriptions.push( vscode.commands.registerCommand('namespaceResolver.expand', async () => { - let selections = vscode.window.activeTextEditor.selections; + let selections = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.selections : []; for (let i = 0; i < selections.length; i++) { await resolver.expandCommand(selections[i]); @@ -77,4 +78,3 @@ function activate(context) { context.subscriptions.push(resolver); } -exports.activate = activate; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..31f66f4 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "lib": [ + "esnext" + ], + "outDir": "out", + "sourceMap": true, + "strict": true, + "rootDir": "src", + "allowJs": true, + "noImplicitAny": false, + "strictNullChecks": false + }, + "exclude": [ + "node_modules", + ".vscode-test", + "out" + ] +} \ No newline at end of file diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..c791efd --- /dev/null +++ b/tslint.json @@ -0,0 +1,15 @@ +{ + "rules": { + "no-string-throw": true, + "no-unused-expression": true, + "no-duplicate-variable": true, + "curly": true, + "class-name": true, + "semicolon": [ + true, + "always" + ], + "triple-equals": true + }, + "defaultSeverity": "warning" +} \ No newline at end of file From 2384b52a05d156a15e35c1e3333ed4fd9e66f04d Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 10 Aug 2019 05:00:42 +0200 Subject: [PATCH 2/2] clean --- src/Parser.ts | 1 - src/Resolver.ts | 1 - src/extension.ts | 2 -- 3 files changed, 4 deletions(-) diff --git a/src/Parser.ts b/src/Parser.ts index 58afac9..28ec2ff 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -47,7 +47,6 @@ export class Parser { } private getExtendedClasses(parsedCode: any): ClassInfo[] { - const classBody = this.getClass(parsedCode); if (!classBody) { return []; diff --git a/src/Resolver.ts b/src/Resolver.ts index 0914a5e..e4a1d43 100644 --- a/src/Resolver.ts +++ b/src/Resolver.ts @@ -6,7 +6,6 @@ import builtInClasses from './classes'; import { naturalSort } from 'node-natural-sort'; import { window, workspace, TextEditor, Range, Position, Selection, TextEditorDecorationType } from 'vscode'; - export class Resolver { private decorationTypeForNotImported: TextEditorDecorationType; private decorationTypeForNotUsed: TextEditorDecorationType; diff --git a/src/extension.ts b/src/extension.ts index 79e61e5..eb03a43 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,5 +1,3 @@ -/* let vscode = require('vscode'); -let Resolver = require('./Resolver'); */ import * as vscode from 'vscode'; import { Resolver } from './Resolver'; export function activate(context: { subscriptions: any }) {