Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7421d68
Adding Yeoman based generator and environment to VSCode extension.
ricardo-espinoza Jul 11, 2020
65f51d6
Move prompting logic into yeoman generator.
ricardo-espinoza Jul 12, 2020
734d83d
Fixing .vscodeignore file to exclude unnecessary files from the VSIX.
ricardo-espinoza Jul 12, 2020
efbc612
Renaming template files to remove unnecessary .txt extension.
ricardo-espinoza Jul 13, 2020
4f4cb28
Updating .gitignore files.
ricardo-espinoza Jul 13, 2020
997240c
Copying the templated files and opening the project
ricardo-espinoza Jul 13, 2020
ad067bb
Setting project namespace correctly using the templates.
ricardo-espinoza Jul 13, 2020
eed4bd7
Setting path to read template files from VSIX.
ricardo-espinoza Jul 13, 2020
e49be05
Name project executable according to desired namespace.
ricardo-espinoza Jul 13, 2020
588fb4a
Merge branch 'master' into ricardoe/templates/yeoman-direct
ricardo-espinoza Jul 14, 2020
55d4641
Merge branch 'master' into ricardoe/templates/yeoman-direct
ricardo-espinoza Jul 14, 2020
435b6fa
Rename command to install templates to clarify they are for CL.
ricardo-espinoza Jul 15, 2020
b44604d
Merge branch 'master' into ricardoe/templates/yeoman-direct
ricardo-espinoza Jul 15, 2020
fb845e0
Update src/VSCodeExtension/templates/unittest/Tests.qs
ricardo-espinoza Jul 15, 2020
e02d4e7
Update src/VSCodeExtension/templates/unittest/Tests.qs
ricardo-espinoza Jul 15, 2020
850da41
Update src/VSCodeExtension/templates/unittest/Tests.qs
ricardo-espinoza Jul 15, 2020
591f865
Update src/VSCodeExtension/templates/library/Library.qs
ricardo-espinoza Jul 15, 2020
2b3db23
Update src/VSCodeExtension/templates/application/Program.qs
ricardo-espinoza Jul 15, 2020
dac7140
Update src/VSCodeExtension/templates/application/Program.qs
ricardo-espinoza Jul 15, 2020
4e8986c
Update src/VSCodeExtension/templates/library/Library.qs
ricardo-espinoza Jul 15, 2020
3280d21
Pull request feedback on error handling.
ricardo-espinoza Jul 15, 2020
04b5563
Merge branch 'master' into ricardoe/templates/yeoman-direct
ricardo-espinoza Jul 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/VSCodeExtension/.vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
out/test/**
out/**/*.map
src/**
.gitignore
**/.gitignore
tsconfig.json
vsc-extension-quickstart.md
tslint.json
Build-Dependencies.ps1
BUILDING.md
*.v.template
**/*.v.template
10 changes: 9 additions & 1 deletion src/VSCodeExtension/package.json.v.template
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"commands": [
{
"command": "quantum.installTemplates",
"title": "Q#: Install project templates"
"title": "Q#: Install command line project templates"
},

{
Expand Down Expand Up @@ -114,13 +114,21 @@
"vscode-extension-telemetry": "0.0.18",
"vscode-languageclient": "5.1.0",
"which": "1.3.1",
"yeoman-environment": "^2.10.3",
"yeoman-generator": "^2.0.1",
"yosay": "^2.0.1",
"@types/fs-extra": "^8.0.0"
},
"devDependencies": {
"vscode": "^1.1.34",
"typescript": "^2.6.1",
"tslint": "^5.8.0",
"mocha": "^5.2.0",
"@types/yeoman-generator": "^3.1.4",
"@types/yosay": "^0.0.29",
"yeoman-test": "^1.7.0",
"yeoman-assert": "^3.1.0",
"@types/yeoman-environment": "^2.3.3",
"@types/node": "^9.6.5",
"@types/mocha": "^5.2.0",
"@types/which": "1.3.1",
Expand Down
113 changes: 13 additions & 100 deletions src/VSCodeExtension/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { IPackageInfo } from './packageInfo';
import * as semver from 'semver';
import { promisify } from 'util';
import { oc } from 'ts-optchain';
import { QSharpGenerator } from './yeoman-generator';

import * as yeoman from 'yeoman-environment';

export function registerCommand(context: vscode.ExtensionContext, name: string, action: () => void) {
context.subscriptions.push(
Expand All @@ -22,107 +25,17 @@ export function registerCommand(context: vscode.ExtensionContext, name: string,
)
}

function createNewProjectAtUri(dotNetSdk: DotnetInfo, projectType: string, uri: vscode.Uri) {
let proc = cp.spawn(
dotNetSdk.path,
["new", projectType, "-lang", "Q#", "-o", uri.fsPath]
);

let errorMessage = "";
proc.stderr.on('data', data => {
errorMessage = errorMessage + data;
});

proc.on(
'exit', (code, signal) => {
if (code === 0) {
const openItem = "Open new project...";
vscode.window.showInformationMessage(
`Successfully created new project at ${uri.fsPath}.`,
openItem
).then(
(item) => {
if (item === openItem) {
vscode.commands.executeCommand(
"vscode.openFolder",
uri
).then(
(value) => {},
(value) => {
vscode.window.showErrorMessage("Could not open new project");
}
);
}
}
);
} else {
// Check if the problem was that the project templates are missing.
// If so, we can give a more helpful error message and offer the
// user to install templates.
if (errorMessage.includes("Q#") && errorMessage.includes("-lang")) {
const installTemplatesItem = "Install project templates and retry";
vscode.window.showErrorMessage(
"Project creation failed. The Q# project templates may not be installed.",
installTemplatesItem
)
.then(
item => {
if (item === installTemplatesItem) {
vscode.commands.executeCommand(
"quantum.installTemplates"
).then(
() => createNewProjectAtUri(dotNetSdk, projectType, uri)
);
}
}
);
} else {
vscode.window.showErrorMessage(
`.NET Core SDK exited with code ${code} when creating a new project:\n${errorMessage}`
);
}
}
export function createNewProject(context: vscode.ExtensionContext) {
let env = yeoman.createEnv();
env.options.extensionPath = context.extensionPath;
env.registerStub(QSharpGenerator, 'qsharp:app');
env.run('qsharp:app', (err: null | Error) => {
if (err) {
let errorMessage = err.name + ": " + err.message;
console.log(errorMessage);
vscode.window.showErrorMessage(errorMessage);
}
);
}

export function createNewProject(dotNetSdk: DotnetInfo) {
const projectTypes: {[key: string]: string} = {
"Standalone console application": "console",
"Quantum library": "classlib",
"Unit testing project": "xunit"
};
vscode.window.showQuickPick(
Object.keys(projectTypes)
).then(
projectTypeSelection => {
if (projectTypeSelection === undefined) {
throw undefined;
}
let projectType = projectTypes[projectTypeSelection];

vscode.window.showSaveDialog({
saveLabel: "Create Project"
}).then(
(uri) => {
if (uri !== undefined) {
if (uri.scheme !== "file") {
vscode.window.showErrorMessage(
"New projects must be saved to the filesystem."
);
throw new Error("URI scheme was not file.");
}
else {
return uri;
}
} else {
throw undefined;
}
}
)
.then(uri => createNewProjectAtUri(dotNetSdk, projectType, uri));
}
);
});
}

export function installTemplates(dotNetSdk: DotnetInfo, packageInfo?: IPackageInfo) {
Expand Down
2 changes: 1 addition & 1 deletion src/VSCodeExtension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export async function activate(context: vscode.ExtensionContext) {
context,
"quantum.newProject",
() => {
requireDotNetSdk(dotNetSdkVersion).then(createNewProject);
createNewProject(context);
}
);

Expand Down
123 changes: 123 additions & 0 deletions src/VSCodeExtension/src/yeoman-generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import * as vscode from 'vscode';
import * as fs from 'fs-extra';
import * as path from 'path';
import yo = require("yeoman-generator");
import yosay = require("yosay");

export class QSharpGenerator extends yo {

constructor(args : any, opts : any) {
super(args, opts);
console.log(
yosay("Welcome to the Q# generator!")
);

this.sourceRoot(path.join(this.options.extensionPath, "templates"));
}

prompting() {
let done = this.async();

// This dictionary maps the public description of the project type to the name
// of the folder with the corresponding template files.
const projectTypes: {[key: string]: string} = {
"Standalone console application": "application",
"Quantum library": "library",
"Unit testing project": "unittest"
};

vscode.window.showQuickPick(
Comment thread
ricardo-espinoza marked this conversation as resolved.
Object.keys(projectTypes)
).then(
projectTypeSelection => {
if (projectTypeSelection === undefined) {
throw undefined;
}

vscode.window.showSaveDialog({
saveLabel: "Create Project"
}).then(
(uri) => {
if (uri !== undefined) {
if (uri.scheme !== "file") {
vscode.window.showErrorMessage(
"New projects must be saved to the filesystem."
);
throw new Error("URI scheme was not file.");
}
else {
return uri;
}
} else {
throw undefined;
}
}
)
.then(uri => {
this.options.projectType = projectTypes[projectTypeSelection];
this.options.outputUri = uri;
done();
});
}
);
}

writing() {
console.log(
yosay("Creating Q# project.")
);

let sourceDir = path.join(this.templatePath(), this.options.projectType);
let targetDir = this.options.outputUri.fsPath;
fs.mkdir(targetDir);

// Namespace is the directory name itself.
let dirs = targetDir.split(path.sep);

// In case there is a trailing separator.
let namespaceName = dirs.pop() || dirs.pop();

fs.readdir(sourceDir, (err, files) => {
if (err){
throw err;
}
files.forEach( (filename) => {
let destinationName = filename;
let fileExtension = filename.split(".").pop();

if (fileExtension && fileExtension.toLowerCase() === "csproj") {
destinationName = namespaceName + ".csproj";
}

this.fs.copyTpl(
path.join(sourceDir, filename),
path.join(targetDir, destinationName),
{ name: namespaceName }
);
});
});

const openItem = "Open new project...";
vscode.window.showInformationMessage(
`Successfully created new project at ${targetDir}.`,
openItem
).then(
(item) => {
if (item === openItem) {
vscode.commands.executeCommand(
"vscode.openFolder",
this.options.outputUri
).then(
(value) => { },
(value) => {
vscode.window.showErrorMessage("Could not open new project");
}
);
}
}
);
}
}
2 changes: 2 additions & 0 deletions src/VSCodeExtension/templates/application/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Generated or copied files
*.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.Quantum.Sdk/#NUGET_VERSION#">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

</Project>
10 changes: 10 additions & 0 deletions src/VSCodeExtension/templates/application/Program.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace <%= name %> {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;


@EntryPoint()
operation SayHello() : Unit {
Message("Hello quantum world!");
}
}
2 changes: 2 additions & 0 deletions src/VSCodeExtension/templates/library/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Generated or copied files
*.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.Quantum.Sdk/#NUGET_VERSION#">

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>

</Project>
9 changes: 9 additions & 0 deletions src/VSCodeExtension/templates/library/Library.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace <%= name %> {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;


operation SayHello() : Unit {
Message("Hello quantum world!");
}
}
2 changes: 2 additions & 0 deletions src/VSCodeExtension/templates/unittest/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Generated or copied files
*.csproj
Comment thread
ricardo-espinoza marked this conversation as resolved.
16 changes: 16 additions & 0 deletions src/VSCodeExtension/templates/unittest/Test.csproj.v.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.Quantum.Sdk/#NUGET_VERSION#">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Xunit" Version="#NUGET_VERSION#" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions src/VSCodeExtension/templates/unittest/Tests.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace <%= name %> {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic;


@Test("QuantumSimulator")
operation AllocateQubit() : Unit {

using (q = Qubit()) {
Assert([PauliZ], [q], Zero, "Newly allocated qubit must be in |0> state.");
}

Message("Test passed.");
}
}