Round trip with SSDT (#10563)

* Initial changes

* Round trip feature implementation

* Addressed PR comments

* Addressed comments
This commit is contained in:
Sakshi Sharma
2020-05-27 07:23:47 -07:00
committed by GitHub
parent 7496d09eb9
commit f49bfbc91b
4 changed files with 108 additions and 10 deletions

View File

@@ -8,7 +8,7 @@ import * as xmldom from 'xmldom';
import * as constants from '../common/constants';
import * as utils from '../common/utils';
import { Uri } from 'vscode';
import { Uri, window } from 'vscode';
import { promises as fs } from 'fs';
import { DataSource } from './dataSources/dataSources';
@@ -20,6 +20,7 @@ export class Project {
public projectFileName: string;
public files: ProjectEntry[] = [];
public dataSources: DataSource[] = [];
public importedTargets: string[] = [];
public sqlCmdVariables: Record<string, string> = {};
public get projectFolderPath() {
@@ -41,7 +42,6 @@ export class Project {
this.projFileXmlDoc = new xmldom.DOMParser().parseFromString(projFileText.toString());
// find all folders and files to include
for (let ig = 0; ig < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup).length; ig++) {
const itemGroup = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup)[ig];
@@ -53,6 +53,45 @@ export class Project {
this.files.push(this.createProjectEntry(itemGroup.getElementsByTagName(constants.Folder)[f].getAttribute(constants.Include), EntryType.Folder));
}
}
// find all import statements to include
for (let i = 0; i < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Import).length; i++) {
const importTarget = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Import)[i];
this.importedTargets.push(importTarget.getAttribute(constants.Project));
}
}
public async updateProjectForRoundTrip() {
if (this.importedTargets.includes(constants.NetCoreTargets)) {
return;
}
window.showWarningMessage(constants.updateProjectForRoundTrip, constants.yesString, constants.noString).then(async (result) => {
if (result === constants.yesString) {
await fs.copyFile(this.projectFilePath, this.projectFilePath + '_backup');
await this.updateImportToSupportRoundTrip();
await this.updatePackageReferenceInProjFile();
}
});
}
private async updateImportToSupportRoundTrip(): Promise<void> {
// update an SSDT project to include Net core target information
for (let i = 0; i < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Import).length; i++) {
const importTarget = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Import)[i];
let condition = importTarget.getAttribute(constants.Condition);
let project = importTarget.getAttribute(constants.Project);
if (condition === constants.SqlDbPresentCondition && project === constants.SqlDbTargets) {
await this.updateImportedTargetsToProjFile(constants.RoundTripSqlDbPresentCondition, project, importTarget);
}
if (condition === constants.SqlDbNotPresentCondition && project === constants.MsBuildtargets) {
await this.updateImportedTargetsToProjFile(constants.RoundTripSqlDbNotPresentCondition, project, importTarget);
}
}
await this.updateImportedTargetsToProjFile(constants.NetCoreCondition, constants.NetCoreTargets, undefined);
}
/**
@@ -109,14 +148,17 @@ export class Project {
private findOrCreateItemGroup(containedTag?: string): any {
let outputItemGroup = undefined;
// find any ItemGroup node that contains files; that's where we'll add
for (let i = 0; i < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup).length; i++) {
const currentItemGroup = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup)[i];
// search for a particular item goup if a child type is provided
if (containedTag) {
// find any ItemGroup node that contains files; that's where we'll add
for (let ig = 0; ig < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup).length; ig++) {
const currentItemGroup = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ItemGroup)[ig];
// if we're not hunting for a particular child type, or if we are and we find it, use the ItemGroup
if (!containedTag || currentItemGroup.getElementsByTagName(containedTag).length > 0) {
outputItemGroup = currentItemGroup;
break;
// if we find the tag, use the ItemGroup
if (currentItemGroup.getElementsByTagName(containedTag).length > 0) {
outputItemGroup = currentItemGroup;
break;
}
}
}
@@ -143,6 +185,34 @@ export class Project {
this.findOrCreateItemGroup(constants.Folder).appendChild(newFolderNode);
}
private async updateImportedTargetsToProjFile(condition: string, project: string, oldImportNode?: any): Promise<any> {
const importNode = this.projFileXmlDoc.createElement(constants.Import);
importNode.setAttribute(constants.Condition, condition);
importNode.setAttribute(constants.Project, project);
if (oldImportNode) {
this.projFileXmlDoc.documentElement.replaceChild(importNode, oldImportNode);
}
else {
this.projFileXmlDoc.documentElement.appendChild(importNode, oldImportNode);
}
await this.serializeToProjFile(this.projFileXmlDoc);
return importNode;
}
private async updatePackageReferenceInProjFile(): Promise<void> {
const packageRefNode = this.projFileXmlDoc.createElement(constants.PackageReference);
packageRefNode.setAttribute(constants.Condition, constants.NetCoreCondition);
packageRefNode.setAttribute(constants.Include, constants.NETFrameworkAssembly);
packageRefNode.setAttribute(constants.Version, constants.VersionNumber);
packageRefNode.setAttribute(constants.PrivateAssets, constants.All);
this.findOrCreateItemGroup(constants.PackageReference).appendChild(packageRefNode);
await this.serializeToProjFile(this.projFileXmlDoc);
}
private async addToProjFile(entry: ProjectEntry) {
switch (entry.type) {
case EntryType.File: