Handling file deletion and on change events on fil (#19)

* Resolving the security vulnerability

* Added the changes for handling on change and delete events on .ts and .html files.
This commit is contained in:
manpatel3107 2019-01-09 15:38:50 -08:00 коммит произвёл GitHub
Родитель 2a15eb86b8
Коммит 919f8c558a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 315 добавлений и 76 удалений

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "mezzurite",
"displayName": "Microsoft",
"displayName": "Mezzurite",
"description": "Instrument your application with Mezzurite SDK quickly and easily with this extension.",
"version": "2.0.0",
"publisher": "mezzurite-devs",

Просмотреть файл

@ -6,6 +6,7 @@ const ExtensionConstants = {
pathForAppsPackageJson : "**/package.json",
pathForNodeModules : "**/node_modules/**",
pathForTypescriptFiles : "**/*.ts",
pathForHtmlFiles : "**/*.html",
titleForWelcomePage : "Mezzurite Extension",
placeholderForStyleTag : "##StyleLink##",
webviewStyleName : "style.css",
@ -39,18 +40,26 @@ const ExtensionConstants = {
mezzuriteAngularJs:"@microsoft/mezzurite-angularjs",
mezzuriteAngular:"@microsoft/mezzurite-angular",
mezzuriteReact:"@microsoft/mezzurite-react",
componentsNotFound: "No components found!",
modulesNotFound: "No modules found!",
notFoundId:"NotFound",
githubRepo:"Click here to visit out Github Repository!",
mezzuGithubUrl:"https://github.com/Microsoft/Mezzurite"
}
const CommandConstants = {
validateMezzuriteCommand : "extension.validateMezzurite",
displayLandingPageCommand : "extension.displayLandingPage",
trackComponentCommand: "componentTreeView.selectNode",
trackModuleCommand:"moduleTreeView.selectNode"
trackModuleCommand:"moduleTreeView.selectNode",
openUrl:"vscode.open"
}
const TreeviewTitleConstants = {
markedComponent:"This component is marked for performance tracking.",
unmarkedComponent:"Missing 'mezzurite' directive. Missing 'component-title' directive.",
unmarkedComponent:"Missing 'mezzurite' and 'component-title' directive.",
markedModule:"This module is marked for performance tracking.",
missingMezzuImport:"Missing mezzurite import declaration.",
missingMezzuForRoot:"Missing AngularPerfModule.forRoot() statement.",

Просмотреть файл

@ -1,5 +1,6 @@
import {ExtensionConstants} from './constants/extension-constants';
import {MezzuriteAngularV1} from './frameworks/mezzurite-angular';
import {MezzuriteUtils} from './utils/mezzurite-utils';
export class ExecuteMezzuriteFrameworkRules {
private frameworkName: string;
@ -24,7 +25,10 @@ export class ExecuteMezzuriteFrameworkRules {
break;
default: console.log('Mezzurite framework name '+ this.frameworkName + ' or version '+ this.frameworkversion +' is invalid!');
}
return await mezzuriteFramework.executeFrameworkSpecificRules();
if(mezzuriteFramework){
return await mezzuriteFramework.executeFrameworkSpecificRules();
}
return MezzuriteUtils.createOutputObject([], []);
}
}

Просмотреть файл

@ -11,6 +11,10 @@ import {MezzuriteExtension} from './mezzurite-extension-main';
export async function activate(context: vscode.ExtensionContext) {
// create a new Mezzurite extension
let mezzuriteExtension = new MezzuriteExtension();
// Create file system watcher for .ts and .html files
let tsFileSystemWatcher = vscode.workspace.createFileSystemWatcher(ExtensionConstants.pathForTypescriptFiles, false, true, false);
let htmlFileSystemWatcher = vscode.workspace.createFileSystemWatcher(ExtensionConstants.pathForHtmlFiles, false, true, false);
// Check if mezzurite dependency is found or not
var mezzuriteDependency: any = await mezzuriteExtension.verifyMezzurite();
@ -25,6 +29,7 @@ export async function activate(context: vscode.ExtensionContext) {
let validateMezzurite = commands.registerCommand( CommandConstants.validateMezzuriteCommand, async () => {
let updatedResults = await mezzuriteExtension.executeMezzuriteRules(mezzuriteDependency, undefined);
mezzuriteExtension.displayComponentsTreeView(updatedResults, context);
mezzuriteExtension.displayModulesTreeView(updatedResults, context);
});
// Display components treeview
@ -33,17 +38,25 @@ export async function activate(context: vscode.ExtensionContext) {
// Display modules treeview
mezzuriteExtension.displayModulesTreeView(ruleResults, context);
// Command for On Save of a .ts or .html file
vscode.workspace.onDidSaveTextDocument(async (document) => {
if(document.languageId === ExtensionConstants.typescript){
let updatedResults = await mezzuriteExtension.executeMezzuriteRules(mezzuriteDependency, document.fileName);
updatedResults = mezzuriteExtension.mergeResultsAfterSave(ruleResults, updatedResults);
mezzuriteExtension.displayComponentsTreeView(updatedResults, context);
ruleResults = await mezzuriteExtension.onEditOrCreateTsFile(ruleResults, mezzuriteDependency, document.fileName, context);
}
else if(document.languageId === ExtensionConstants.html){
// @TODO: This is in progress
// Check if that html file is present inside oldResults.listOfComponents and verifying the 'templateUrl' property
ruleResults = await mezzuriteExtension.onEditOrCreateHtmlFile(ruleResults, document.fileName, context);
}
});
});
// Command for On Delete of a .ts file
tsFileSystemWatcher.onDidDelete(async function(e){
ruleResults = await mezzuriteExtension.onDeleteTsFile(ruleResults, e.fsPath, context);
});
// Command for On Delete of a .html file
htmlFileSystemWatcher.onDidDelete(async function(e){
ruleResults = await mezzuriteExtension.onDeleteHtmlFile(ruleResults, e.fsPath, context);
});
// Command for displaying the landing page
let landingPageCommand = commands.registerCommand( CommandConstants.displayLandingPageCommand, () => {
@ -52,19 +65,28 @@ export async function activate(context: vscode.ExtensionContext) {
// Command for selecting a node in components tree view
let componentsTreeView = commands.registerCommand(CommandConstants.trackComponentCommand, (item: any) => {
vscode.workspace.openTextDocument(item.path).then(doc => {
vscode.window.showTextDocument(doc);
});
if(item.path === ExtensionConstants.notFoundId){
vscode.commands.executeCommand(CommandConstants.openUrl, vscode.Uri.parse(ExtensionConstants.mezzuGithubUrl))
}
else{
vscode.workspace.openTextDocument(item.path).then(doc => {
vscode.window.showTextDocument(doc);
});
}
});
// Command for selecting a node in components tree view
// Command for selecting a node in modules tree view
let modulesTreeView = commands.registerCommand(CommandConstants.trackModuleCommand, (item: any) => {
vscode.workspace.openTextDocument(item.path).then(doc => {
vscode.window.showTextDocument(doc);
});
if(item.path === ExtensionConstants.notFoundId){
vscode.commands.executeCommand(CommandConstants.openUrl, vscode.Uri.parse(ExtensionConstants.mezzuGithubUrl))
}
else{
vscode.workspace.openTextDocument(item.path).then(doc => {
vscode.window.showTextDocument(doc);
});
}
});
context.subscriptions.push(validateMezzurite);
context.subscriptions.push(landingPageCommand);
context.subscriptions.push(componentsTreeView);

Просмотреть файл

@ -25,7 +25,7 @@ export class MezzuriteAngularV1{
files = await MezzuriteUtils.searchWorkspace(workspace, ExtensionConstants.pathForTypescriptFiles, ExtensionConstants.pathForNodeModules);
}
else{
var editedFilePath = "**/" + MezzuriteAngularV1.getFileNameFromPath(this.filePath);
var editedFilePath = "**/" + MezzuriteUtils.getFileNameFromPath(this.filePath);
files = await MezzuriteUtils.searchWorkspace(workspace, editedFilePath, ExtensionConstants.pathForNodeModules);
}
let data: string;
@ -46,14 +46,7 @@ export class MezzuriteAngularV1{
listOfComponents = await MezzuriteAngularV1.getListOfComponents(filePath, data, listOfComponents);
}
}
return MezzuriteAngularV1.outputObject(listOfComponents, listOfModules);
}
static outputObject(listOfComponents: any, listOfModules: any){
var outputObj: any = {};
outputObj["listOfComponents"] = listOfComponents;
outputObj["listOfModules"] = listOfModules;
return outputObj;
return MezzuriteUtils.createOutputObject(listOfComponents, listOfModules);
}
/**
@ -302,7 +295,7 @@ export class MezzuriteAngularV1{
// Look for 'template' and 'templateUrl' properties in decorator object
var templateUrlProperty = MezzuriteAngularV1.getDecoratorProperty(decorator, ExtensionConstants.templateUrl);
if(templateUrlProperty !== undefined && templateUrlProperty !== ""){
MezzuriteAngularV1.checkForTemplateUrlProperty(templateUrlProperty, componentObject);
await MezzuriteAngularV1.checkForTemplateUrlProperty(templateUrlProperty, componentObject);
}
var templateProperty = MezzuriteAngularV1.getDecoratorProperty(decorator, ExtensionConstants.template);
if(templateProperty !== undefined && templateProperty !== ""){
@ -320,8 +313,8 @@ export class MezzuriteAngularV1{
var templateUrlValue = templateUrlProperty.getInitializer().compilerNode.text;
if(templateUrlValue !== ""){
componentObject.templateUrl = templateUrlValue;
var fileName: string = MezzuriteAngularV1.getFileNameFromPath(templateUrlValue);
var found = await MezzuriteAngularV1.parseExternalHTMLFile(fileName);
var fileName: string = MezzuriteUtils.getFileNameFromPath(templateUrlValue);
var found = await MezzuriteUtils.parseExternalHTMLFile(fileName, workspace);
if(found){
componentObject.status = ExtensionConstants.marked;
}
@ -337,7 +330,7 @@ export class MezzuriteAngularV1{
var templateValue = templateProperty.getInitializer().compilerNode.text;
if(templateValue !== ""){
componentObject.template = ExtensionConstants.htmlTemplateProvided;
if(MezzuriteAngularV1.verifyComponentMarking(templateValue)){
if(MezzuriteUtils.verifyComponentMarking(templateValue)){
componentObject.status = ExtensionConstants.marked;
}
}
@ -373,40 +366,5 @@ export class MezzuriteAngularV1{
return moduleObject;
}
/**
* This method is used to get the html file name from file path
* @param filePath of the html template
* @return heml file name
*/
static getFileNameFromPath(filePath: string){
var lastIndex = filePath.lastIndexOf('/') > -1? filePath.lastIndexOf('/') : filePath.lastIndexOf('\\');
return filePath.substring(lastIndex + 1, filePath.length);
}
/**
* This method is used to parse the html template for the components with templateUrl property
* @param filePath of the html template
* @return true, if parsed html is marked for tracking, otherwise, false
*/
static async parseExternalHTMLFile(fileName: string){
var templateString: any;
// Get the html file and parse its contents for mezzurite markings
let files: any = await MezzuriteUtils.searchWorkspace(workspace, "**/" + fileName, ExtensionConstants.pathForNodeModules);
if(files[0] && files[0].fsPath){
templateString = MezzuriteUtils.readFileFromWorkspace(files[0].fsPath, 'utf8');
}
return MezzuriteAngularV1.verifyComponentMarking(templateString);
}
/**
* This method verifies whether component is marked or not
* @param htmlString is the html template of the component
* @return true, if parsed html contains the mezzurite directive and component-title, otherwise, false
*/
static verifyComponentMarking(htmlString: string){
if(htmlString && htmlString.indexOf(ExtensionConstants.mezzuriteDirective) > -1 && htmlString.indexOf(ExtensionConstants.componentTitleDirective)> -1){
return true;
}
return false;
}
}

Просмотреть файл

@ -1,9 +1,11 @@
import * as vscode from 'vscode';
import {workspace} from 'vscode';
import {LandingPage} from './landing-page';
import {MezzuriteDependency} from './verify-mezzurite-dependency';
import {ExecuteMezzuriteFrameworkRules} from './execute-mezzurite-framework-rules';
import {ComponentsProvider} from './treeview/components-treeview'
import {ModulesProvider} from './treeview/modules-treeview'
import {ModulesProvider} from './treeview/modules-treeview';
import {MezzuriteUtils} from './utils/mezzurite-utils';
import { ExtensionConstants } from './constants/extension-constants';
/**
* Mezzurite extension class
@ -46,6 +48,66 @@ export class MezzuriteExtension{
}
}
/**
* This method updates the output results whenever a typescript file is created or edited and then saved
* @param list of old modules or components output data
* @param mezzurite dependency object
* @param filepath of changed file
* @param context which is editor context needed to display the output
* @return returns array of modules or components
*/
public async onEditOrCreateTsFile(ruleResults: any, mezzuriteDependency: any, filePath: string, context: any){
let updatedResults = await this.executeMezzuriteRules(mezzuriteDependency, filePath);
updatedResults = this.mergeResultsAfterSave(ruleResults, updatedResults);
this.displayComponentsTreeView(updatedResults, context);
this.displayModulesTreeView(updatedResults, context);
return updatedResults;
}
/**
* This method updates the output results whenever a typescript file is deleted
* @param list of old modules or components output data
* @param filepath of changed file
* @param context which is editor context needed to display the output
* @return returns array of modules or components
*/
public async onDeleteTsFile(ruleResults: any, filePath: string, context: any){
var updatedResults: any = {};
updatedResults["listOfComponents"] = MezzuriteExtension.removeComponentOnDelete(ruleResults.listOfComponents, filePath);
updatedResults["listOfModules"] = MezzuriteExtension.removeModuleOnDelete(ruleResults.listOfModules, filePath);
this.displayComponentsTreeView(updatedResults, context);
this.displayModulesTreeView(updatedResults, context);
return updatedResults;
}
/**
* This method updates the output results whenever a html file is created or edited and then saved
* @param list of old modules or components output data
* @param filepath of changed file
* @param context which is editor context needed to display the output
* @return returns array of modules or components
*/
public async onEditOrCreateHtmlFile(ruleResults: any, filePath: string, context: any){
let updatedResults = await this.verifyHtmlComponent(ruleResults, filePath);
this.displayComponentsTreeView(updatedResults, context);
return updatedResults;
}
/**
* This method updates the output results whenever a html file is deleted
* @param list of old modules or components output data
* @param filepath of changed file
* @param context which is editor context needed to display the output
* @return returns array of modules or components
*/
public async onDeleteHtmlFile(ruleResults: any, filePath: string, context: any){
var updatedResults: any = {};
updatedResults["listOfComponents"] = MezzuriteExtension.removeHtmlComponentOnDelete(ruleResults.listOfComponents, filePath);
updatedResults["listOfModules"] = ruleResults.listOfModules;
this.displayComponentsTreeView(updatedResults, context);
return updatedResults;
}
/**
* This method creates tree view for all the components present in the workspace
* @param results object consisting of all the components
@ -64,12 +126,123 @@ export class MezzuriteExtension{
vscode.window.registerTreeDataProvider(ExtensionConstants.modulesTreeview, treeView);
}
/**
* This method merge the old output data with a newly saved or created module or component data
* @param list of old modules or components output data
* @param list of newly saved or created modules or component
* @return returns merged array of modules or components
*/
public mergeResultsAfterSave(oldResults: any, newResults: any){
var updatedResults;
// Merge components
if(newResults.listOfComponents.length > 0){
updatedResults = MezzuriteExtension.mergeComponentsAfterSave(oldResults, newResults);
}
// Merge Modules
if(newResults.listOfModules.length > 0){
updatedResults = MezzuriteExtension.mergeModulesAfterSave(oldResults,newResults);
}
return updatedResults;
}
/**
* This method merge the old components output data with a newly saved or created component data
* @param list of old components output data
* @param list of newly saved or created component
* @return returns merged array of components to be displayed
*/
public static mergeComponentsAfterSave(oldResults: any, newResults: any){
var found = false;
for(var i=0;i<oldResults.listOfComponents.length;i++){
if(oldResults.listOfComponents[i].componentName === newResults.listOfComponents[0].componentName){
if(oldResults.listOfComponents[i].filePath === newResults.listOfComponents[0].filePath){
oldResults.listOfComponents[i] = newResults.listOfComponents[0];
found = true;
break;
}
}
if(!found){
oldResults.listOfComponents.push(newResults.listOfComponents[0]);
}
return oldResults;
}
/**
* This method merge the old modules output data with a newly saved or created module data
* @param list of old modules output data
* @param list of newly saved or created module
* @return returns merged array of modules to be displayed
*/
public static mergeModulesAfterSave(oldResults: any, newResults: any){
var found = false;
for(var i=0;i<oldResults.listOfModules.length;i++){
if(oldResults.listOfModules[i].filePath === newResults.listOfModules[0].filePath){
oldResults.listOfModules[i] = newResults.listOfModules[0];
found = true;
break;
}
}
if(!found){
oldResults.listOfModules.push(newResults.listOfModules[0]);
}
return oldResults;
}
/**
* This method removes the deleted component from the display list
* @param list of old components output data
* @param deleted file path
* @return returns merged array of components to be displayed
*/
public static removeComponentOnDelete(listOfComponents: any, filePath: string){
return listOfComponents.filter(function(componentObject: any) {
return componentObject.filePath != filePath;
});
}
/**
* This method removes the deleted module from the display list
* @param list of old modules output data
* @param deleted file path
* @return returns merged array of modules to be displayed
*/
public static removeModuleOnDelete(listOfModules: any, filePath: string){
return listOfModules.filter(function(moduleObject: any) {
return moduleObject.filePath != filePath;
});
}
/**
* This method removes the deleted html component from the display list
* @param list of old components output data
* @param deleted html file path
* @return returns merged array of components to be displayed
*/
public static removeHtmlComponentOnDelete(listOfComponents: any, filePath: string){
var fileName = MezzuriteUtils.getFileNameFromPath(filePath);
return listOfComponents.filter(function(componentObject: any) {
return componentObject.templateUrl.indexOf(fileName) === -1;
});
}
/**
* This method verifies mezzurite intrumentation checks for extenal html component file which is aved by the user
* @param list of components output
* @param filepath of the saved html file
* @return returns array of components to be displayed
*/
public async verifyHtmlComponent(oldResults: any, filePath: string){
var fileName = MezzuriteUtils.getFileNameFromPath(filePath);
for(var i=0;i<oldResults.listOfComponents.length;i++){
if(oldResults.listOfComponents[i].templateUrl.indexOf(fileName) > -1){
var found = await MezzuriteUtils.parseExternalHTMLFile(fileName, workspace);
if(found){
oldResults.listOfComponents[i].status = ExtensionConstants.marked;
}
else{
oldResults.listOfComponents[i].status = ExtensionConstants.unmarked;
}
return oldResults;
}
}
}
}

Просмотреть файл

@ -61,7 +61,17 @@ export class ComponentsProvider implements vscode.TreeDataProvider<ComponentItem
}
return componentItems;
}
}else{
var message = new ComponentItem(ExtensionConstants.componentsNotFound, ExtensionConstants.notFoundId, "", ExtensionConstants.githubRepo,
vscode.TreeItemCollapsibleState.None);
message.command = {
command: CommandConstants.trackComponentCommand,
title: '',
arguments: [message]
};
componentItems.push(message);
return componentItems;
}
return [];
}
@ -85,7 +95,7 @@ export class ComponentItem extends vscode.TreeItem {
}
get description(): string {
return this.label;
return "";
}
get pathName(): string {

Просмотреть файл

@ -28,13 +28,13 @@ export class ModulesProvider implements vscode.TreeDataProvider<ModuleItem> {
private getTitleForUnmarkedModules(moduleObject: any){
var title = "";
if(moduleObject.importStmt){
if(!moduleObject.importStmt){
title = title + TreeviewTitleConstants.missingMezzuImport;
}
if(moduleObject.forRoot){
if(!moduleObject.forRoot){
title = title + TreeviewTitleConstants.missingMezzuForRoot;
}
if(moduleObject.routerStart){
if(!moduleObject.routerStart){
title = title + TreeviewTitleConstants.missingMezzuStart;
}
return title;
@ -77,7 +77,19 @@ export class ModulesProvider implements vscode.TreeDataProvider<ModuleItem> {
}
return moduleItems;
}
}
else{
var message = new ModuleItem(ExtensionConstants.modulesNotFound, ExtensionConstants.notFoundId, "", ExtensionConstants.githubRepo,
vscode.TreeItemCollapsibleState.None);
message.command = {
command: CommandConstants.trackModuleCommand,
title: '',
arguments: [message]
};
moduleItems.push(message);
return moduleItems;
}
return [];
}
@ -101,7 +113,7 @@ export class ModuleItem extends vscode.TreeItem {
}
get description(): string {
return this.label;
return "";
}
get pathName(): string {

Просмотреть файл

@ -1,4 +1,5 @@
import * as fs from "fs";
import {ExtensionConstants} from '../constants/extension-constants';
export class MezzuriteUtils {
@ -42,4 +43,54 @@ export class MezzuriteUtils {
return data;
}
/**
* This method verifies whether component is marked or not
* @param htmlString is the html template of the component
* @return true, if parsed html contains the mezzurite directive and component-title, otherwise, false
*/
static verifyComponentMarking(htmlString: string){
if(htmlString && htmlString.indexOf(ExtensionConstants.mezzuriteDirective) > -1 && htmlString.indexOf(ExtensionConstants.componentTitleDirective)> -1){
return true;
}
return false;
}
/**
* This method is used to get the html file name from file path
* @param filePath of the html template
* @return heml file name
*/
static getFileNameFromPath(filePath: string){
var lastIndex = filePath.lastIndexOf('/') > -1? filePath.lastIndexOf('/') : filePath.lastIndexOf('\\');
return filePath.substring(lastIndex + 1, filePath.length);
}
/**
* This method is used to parse the html template for the components with templateUrl property
* @param filePath of the html template
* @return true, if parsed html is marked for tracking, otherwise, false
*/
static async parseExternalHTMLFile(fileName: string, workspace: any){
var templateString: any;
// Get the html file and parse its contents for mezzurite markings
let files: any = await MezzuriteUtils.searchWorkspace(workspace, "**/" + fileName, ExtensionConstants.pathForNodeModules);
if(files[0] && files[0].fsPath){
templateString = MezzuriteUtils.readFileFromWorkspace(files[0].fsPath, 'utf8');
}
return MezzuriteUtils.verifyComponentMarking(templateString);
}
/**
* This method creates an output object to be displayed as results
* @param list of components
* @param list of modules
* @return output object
*/
static createOutputObject(listOfComponents: any, listOfModules: any){
var outputObj: any = {};
outputObj["listOfComponents"] = listOfComponents;
outputObj["listOfModules"] = listOfModules;
return outputObj;
}
}