Initial project references changes (#11648)

* first changes for showing project references

* add tests

* fix interface and formatting

* add try so that project still gets loaded even if dependency project loading fails

* use instanceof

* add circular reference error
This commit is contained in:
Kim Santiago
2020-08-13 16:08:32 -07:00
committed by GitHub
parent d68433ec22
commit f3a48da3fa
9 changed files with 217 additions and 23 deletions

View File

@@ -23,7 +23,7 @@ export class Project {
public files: ProjectEntry[] = [];
public dataSources: DataSource[] = [];
public importedTargets: string[] = [];
public databaseReferences: DatabaseReferenceProjectEntry[] = [];
public databaseReferences: IDatabaseReferenceProjectEntry[] = [];
public sqlCmdVariables: Record<string, string> = {};
public get projectFolderPath() {
@@ -91,11 +91,24 @@ export class Project {
throw new Error(constants.invalidDatabaseReference);
}
let nameNodes = references[r].getElementsByTagName(constants.DatabaseVariableLiteralValue);
let name = nameNodes.length === 1 ? nameNodes[0].childNodes[0].nodeValue : undefined;
this.databaseReferences.push(new DatabaseReferenceProjectEntry(Uri.parse(filepath), name ? DatabaseReferenceLocation.differentDatabaseSameServer : DatabaseReferenceLocation.sameDatabase, name));
const nameNodes = references[r].getElementsByTagName(constants.DatabaseVariableLiteralValue);
const name = nameNodes.length === 1 ? nameNodes[0].childNodes[0].nodeValue : undefined;
this.databaseReferences.push(new DacpacReferenceProjectEntry(Uri.file(filepath), name ? DatabaseReferenceLocation.differentDatabaseSameServer : DatabaseReferenceLocation.sameDatabase, name));
}
}
// find project references
const projectReferences = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ProjectReference);
for (let r = 0; r < projectReferences.length; r++) {
const filepath = projectReferences[r].getAttribute(constants.Include);
if (!filepath) {
throw new Error(constants.invalidDatabaseReference);
}
const nameNodes = projectReferences[r].getElementsByTagName(constants.Name);
const name = nameNodes[0].childNodes[0].nodeValue;
this.databaseReferences.push(new SqlProjectReferenceProjectEntry(Uri.file(utils.getPlatformSafeFileEntryPath(filepath)), name));
}
}
public async updateProjectForRoundTrip() {
@@ -284,7 +297,7 @@ export class Project {
* @param databaseName name of the database
*/
public async addDatabaseReference(uri: Uri, databaseLocation: DatabaseReferenceLocation, databaseName?: string): Promise<void> {
let databaseReferenceEntry = new DatabaseReferenceProjectEntry(uri, databaseLocation, databaseName);
let databaseReferenceEntry = new DacpacReferenceProjectEntry(uri, databaseLocation, databaseName);
await this.addToProjFile(databaseReferenceEntry);
}
@@ -359,7 +372,7 @@ export class Project {
throw new Error(constants.unableToFindObject(path, constants.folderObject));
}
private addDatabaseReferenceToProjFile(entry: DatabaseReferenceProjectEntry): void {
private addDatabaseReferenceToProjFile(entry: IDatabaseReferenceProjectEntry): void {
// check if reference to this database already exists
if (this.databaseReferenceExists(entry)) {
throw new Error(constants.databaseReferenceAlreadyExists);
@@ -374,7 +387,7 @@ export class Project {
}
referenceNode.setAttribute(constants.Include, entry.pathForSqlProj());
this.addDatabaseReferenceChildren(referenceNode, entry.name);
this.addDatabaseReferenceChildren(referenceNode, entry.sqlCmdName);
this.findOrCreateItemGroup(constants.ArtifactReference).appendChild(referenceNode);
this.databaseReferences.push(entry);
@@ -383,12 +396,12 @@ export class Project {
let ssdtReferenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference);
ssdtReferenceNode.setAttribute(constants.Condition, constants.NotNetCoreCondition);
ssdtReferenceNode.setAttribute(constants.Include, (<SystemDatabaseReferenceProjectEntry>entry).ssdtPathForSqlProj());
this.addDatabaseReferenceChildren(ssdtReferenceNode, entry.name);
this.addDatabaseReferenceChildren(ssdtReferenceNode, entry.sqlCmdName);
this.findOrCreateItemGroup(constants.ArtifactReference).appendChild(ssdtReferenceNode);
}
}
private databaseReferenceExists(entry: DatabaseReferenceProjectEntry): boolean {
private databaseReferenceExists(entry: IDatabaseReferenceProjectEntry): boolean {
const found = this.databaseReferences.find(reference => reference.fsUri.fsPath === entry.fsUri.fsPath) !== undefined;
return found;
}
@@ -479,7 +492,7 @@ export class Project {
this.addFolderToProjFile(entry.relativePath);
break;
case EntryType.DatabaseReference:
this.addDatabaseReferenceToProjFile(<DatabaseReferenceProjectEntry>entry);
this.addDatabaseReferenceToProjFile(<IDatabaseReferenceProjectEntry>entry);
break; // not required but adding so that we dont miss when we add new items
}
@@ -567,9 +580,18 @@ export class ProjectEntry {
/**
* Represents a database reference entry in a project file
*/
export class DatabaseReferenceProjectEntry extends ProjectEntry {
constructor(uri: Uri, public databaseLocation: DatabaseReferenceLocation, public name?: string) {
export interface IDatabaseReferenceProjectEntry extends ProjectEntry {
databaseName: string;
sqlCmdName?: string | undefined;
}
export class DacpacReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry {
sqlCmdName: string | undefined;
constructor(uri: Uri, public databaseLocation: DatabaseReferenceLocation, name?: string) {
super(uri, '', EntryType.DatabaseReference);
this.sqlCmdName = name;
}
public get databaseName(): string {
@@ -577,9 +599,10 @@ export class DatabaseReferenceProjectEntry extends ProjectEntry {
}
}
class SystemDatabaseReferenceProjectEntry extends DatabaseReferenceProjectEntry {
constructor(uri: Uri, public ssdtUri: Uri, public name: string) {
class SystemDatabaseReferenceProjectEntry extends DacpacReferenceProjectEntry {
constructor(uri: Uri, public ssdtUri: Uri, name: string) {
super(uri, DatabaseReferenceLocation.differentDatabaseSameServer, name);
this.sqlCmdName = name;
}
public pathForSqlProj(): string {
@@ -593,6 +616,19 @@ class SystemDatabaseReferenceProjectEntry extends DatabaseReferenceProjectEntry
}
}
export class SqlProjectReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry {
projectName: string;
constructor(uri: Uri, name: string) {
super(uri, '', EntryType.DatabaseReference);
this.projectName = name;
}
public get databaseName(): string {
return this.projectName;
}
}
export enum EntryType {
File,
Folder,

View File

@@ -57,8 +57,8 @@ async function readConnectionString(xmlDoc: any): Promise<{ connectionId: string
let targetConnectionString: string = '';
let connId: string = '';
if (xmlDoc.documentElement.getElementsByTagName('TargetConnectionString').length > 0) {
targetConnectionString = xmlDoc.documentElement.getElementsByTagName('TargetConnectionString')[0].textContent;
if (xmlDoc.documentElement.getElementsByTagName(constants.targetConnectionString).length > 0) {
targetConnectionString = xmlDoc.documentElement.getElementsByTagName(constants.TargetConnectionString)[0].textContent;
const dataSource = new SqlConnectionDataSource('temp', targetConnectionString);
const connectionProfile = dataSource.getConnectionProfile();

View File

@@ -10,7 +10,7 @@ import * as constants from '../../common/constants';
import { BaseProjectTreeItem } from './baseTreeItem';
import { ProjectRootTreeItem } from './projectTreeItem';
import { IconPathHelper } from '../../common/iconHelper';
import { DatabaseReferenceProjectEntry } from '../../models/project';
import { IDatabaseReferenceProjectEntry } from '../../models/project';
/**
* Folder for containing references nodes in the tree
@@ -44,7 +44,7 @@ export class DatabaseReferencesTreeItem extends BaseProjectTreeItem {
}
export class DatabaseReferenceTreeItem extends BaseProjectTreeItem {
constructor(private reference: DatabaseReferenceProjectEntry, referencesTreeItem: DatabaseReferencesTreeItem) {
constructor(private reference: IDatabaseReferenceProjectEntry, referencesTreeItem: DatabaseReferencesTreeItem) {
super(vscode.Uri.file(path.join(referencesTreeItem.uri.path, reference.databaseName)), referencesTreeItem);
}