diff --git a/Makefile b/Makefile index 3ca627212..0a20c0d05 100644 --- a/Makefile +++ b/Makefile @@ -30,8 +30,6 @@ install: .PHONY: lint lint: @echo "\033[0;32mLINT:\033[0m" - - @gometalinter pkg/... @gometalinter cmd/lumi/... @gometalinter cmd/lumidl/... diff --git a/cmd/lumijs/lib/compiler/transform.ts b/cmd/lumijs/lib/compiler/transform.ts index 2b914aefe..02d5162c1 100644 --- a/cmd/lumijs/lib/compiler/transform.ts +++ b/cmd/lumijs/lib/compiler/transform.ts @@ -1023,11 +1023,14 @@ export class Transformer { contract.assert(!!idsym, `Expected an ID symbol for '${id.ident}', but it is missing`); tok = await this.resolveTokenFromSymbol(idsym); // note that we intentionally leave object blank, since the token is fully qualified. + if ((idsym.flags & ts.SymbolFlags.Alias) === 0) { + // Mark as dynamic unless this is an alias to a module import. + isDynamic = true; + } } if (isDynamic) { // If the target type is `dynamic`, we cannot perform static lookups; devolve into a dynamic load. - contract.assert(!!object); return this.withLocation(node, { kind: ast.tryLoadDynamicExpressionKind, object: object, diff --git a/cmd/lumijs/tests/output/basic/arrays/Lumipack.json b/cmd/lumijs/tests/output/basic/arrays/Lumipack.json index f1ae7bdb2..d7997544d 100644 --- a/cmd/lumijs/tests/output/basic/arrays/Lumipack.json +++ b/cmd/lumijs/tests/output/basic/arrays/Lumipack.json @@ -1215,10 +1215,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a2", + "kind": "StringLiteral", + "value": "a2", "loc": { "file": "index.ts", "start": { @@ -1303,10 +1303,10 @@ "left": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a2", + "kind": "StringLiteral", + "value": "a2", "loc": { "file": "index.ts", "start": { @@ -1436,10 +1436,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a2", + "kind": "StringLiteral", + "value": "a2", "loc": { "file": "index.ts", "start": { @@ -1524,10 +1524,10 @@ "left": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a2", + "kind": "StringLiteral", + "value": "a2", "loc": { "file": "index.ts", "start": { @@ -1657,10 +1657,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a2", + "kind": "StringLiteral", + "value": "a2", "loc": { "file": "index.ts", "start": { @@ -1745,10 +1745,10 @@ "left": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a2", + "kind": "StringLiteral", + "value": "a2", "loc": { "file": "index.ts", "start": { @@ -2004,10 +2004,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a3", + "kind": "StringLiteral", + "value": "a3", "loc": { "file": "index.ts", "start": { @@ -2121,10 +2121,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a3", + "kind": "StringLiteral", + "value": "a3", "loc": { "file": "index.ts", "start": { @@ -2238,10 +2238,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a3", + "kind": "StringLiteral", + "value": "a3", "loc": { "file": "index.ts", "start": { @@ -2859,10 +2859,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -2978,10 +2978,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -3125,10 +3125,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -3272,10 +3272,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -3417,10 +3417,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -3536,10 +3536,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -3683,10 +3683,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -3830,10 +3830,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -4189,10 +4189,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -4308,10 +4308,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -4455,10 +4455,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -4602,10 +4602,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -4747,10 +4747,10 @@ "right": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -4866,10 +4866,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -5013,10 +5013,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { @@ -5160,10 +5160,10 @@ "object": { "kind": "TryLoadDynamicExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/arrays:index:a6", + "kind": "StringLiteral", + "value": "a6", "loc": { "file": "index.ts", "start": { diff --git a/cmd/lumijs/tests/output/basic/null_undefined/Lumipack.json b/cmd/lumijs/tests/output/basic/null_undefined/Lumipack.json index abd2610ce..b9bf6ac7f 100644 --- a/cmd/lumijs/tests/output/basic/null_undefined/Lumipack.json +++ b/cmd/lumijs/tests/output/basic/null_undefined/Lumipack.json @@ -942,10 +942,10 @@ "expression": { "kind": "InvokeFunctionExpression", "function": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/undefined:index:f", + "kind": "StringLiteral", + "value": "f", "loc": { "file": "index.ts", "start": { @@ -1237,10 +1237,10 @@ "expression": { "kind": "InvokeFunctionExpression", "function": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/undefined:index:g", + "kind": "StringLiteral", + "value": "g", "loc": { "file": "index.ts", "start": { diff --git a/cmd/lumijs/tests/output/basic/props/Lumipack.json b/cmd/lumijs/tests/output/basic/props/Lumipack.json index a08692af0..74c35c11a 100644 --- a/cmd/lumijs/tests/output/basic/props/Lumipack.json +++ b/cmd/lumijs/tests/output/basic/props/Lumipack.json @@ -1023,10 +1023,10 @@ }, "operator": "=", "right": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/props:index:modprop", + "kind": "StringLiteral", + "value": "modprop", "loc": { "file": "index.ts", "start": { @@ -1256,10 +1256,10 @@ "kind": "BinaryOperatorExpression", "operator": "!=", "left": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/props:index:c", + "kind": "StringLiteral", + "value": "c", "loc": { "file": "index.ts", "start": { @@ -1389,10 +1389,10 @@ "right": { "kind": "LoadLocationExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/props:index:c", + "kind": "StringLiteral", + "value": "c", "loc": { "file": "index.ts", "start": { @@ -1568,10 +1568,10 @@ "tok": "f" }, "value": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/props:index:modprop", + "kind": "StringLiteral", + "value": "modprop", "loc": { "file": "index.ts", "start": { @@ -1664,10 +1664,10 @@ "value": { "kind": "LoadLocationExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/props:index:c", + "kind": "StringLiteral", + "value": "c", "loc": { "file": "index.ts", "start": { @@ -1770,10 +1770,10 @@ "property": { "kind": "InvokeFunctionExpression", "function": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/props:index:j", + "kind": "StringLiteral", + "value": "j", "loc": { "file": "index.ts", "start": { @@ -1965,10 +1965,10 @@ "right": { "kind": "LoadLocationExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/props:index:c", + "kind": "StringLiteral", + "value": "c", "loc": { "file": "index.ts", "start": { @@ -2065,10 +2065,10 @@ "left": { "kind": "LoadLocationExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/props:index:c", + "kind": "StringLiteral", + "value": "c", "loc": { "file": "index.ts", "start": { diff --git a/cmd/lumijs/tests/output/basic/super/Lumipack.json b/cmd/lumijs/tests/output/basic/super/Lumipack.json index d3fa4520e..b171332b3 100644 --- a/cmd/lumijs/tests/output/basic/super/Lumipack.json +++ b/cmd/lumijs/tests/output/basic/super/Lumipack.json @@ -1164,10 +1164,10 @@ "function": { "kind": "LoadLocationExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/super:index:b", + "kind": "StringLiteral", + "value": "b", "loc": { "file": "index.ts", "start": { @@ -1262,10 +1262,10 @@ "kind": "BinaryOperatorExpression", "operator": "!=", "left": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/super:index:bgx", + "kind": "StringLiteral", + "value": "bgx", "loc": { "file": "index.ts", "start": { @@ -1363,10 +1363,10 @@ } }, "right": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/super:index:bgx", + "kind": "StringLiteral", + "value": "bgx", "loc": { "file": "index.ts", "start": { @@ -1581,10 +1581,10 @@ "function": { "kind": "LoadLocationExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/super:index:c", + "kind": "StringLiteral", + "value": "c", "loc": { "file": "index.ts", "start": { @@ -1679,10 +1679,10 @@ "kind": "BinaryOperatorExpression", "operator": "!=", "left": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/super:index:cgx", + "kind": "StringLiteral", + "value": "cgx", "loc": { "file": "index.ts", "start": { @@ -1780,10 +1780,10 @@ } }, "right": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/super:index:cgx", + "kind": "StringLiteral", + "value": "cgx", "loc": { "file": "index.ts", "start": { @@ -1910,10 +1910,10 @@ "function": { "kind": "LoadLocationExpression", "object": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/super:index:c", + "kind": "StringLiteral", + "value": "c", "loc": { "file": "index.ts", "start": { @@ -2008,10 +2008,10 @@ "kind": "BinaryOperatorExpression", "operator": "!=", "left": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/super:index:cgy", + "kind": "StringLiteral", + "value": "cgy", "loc": { "file": "index.ts", "start": { @@ -2109,10 +2109,10 @@ } }, "right": { - "kind": "LoadLocationExpression", + "kind": "TryLoadDynamicExpression", "name": { - "kind": "Token", - "tok": "basic/super:index:cgy", + "kind": "StringLiteral", + "value": "cgy", "loc": { "file": "index.ts", "start": { diff --git a/examples/scenarios/aws/serverless/Lumi.yaml b/examples/scenarios/aws/serverless/Lumi.yaml index dbbe728d2..fd6ae91f6 100644 --- a/examples/scenarios/aws/serverless/Lumi.yaml +++ b/examples/scenarios/aws/serverless/Lumi.yaml @@ -2,5 +2,6 @@ name: serverless description: Basic example of a serverless AWS application. dependencies: lumi: "*" + lumijs: "*" aws: "*" diff --git a/examples/scenarios/aws/serverless/index.ts b/examples/scenarios/aws/serverless/index.ts index e64817a35..689685794 100644 --- a/examples/scenarios/aws/serverless/index.ts +++ b/examples/scenarios/aws/serverless/index.ts @@ -49,34 +49,17 @@ let music = new aws.dynamodb.Table("music", { ], }) -// TODO[pulumi/lumi#174] Until we have global definitions available in Lumi for these APIs that are expected -// by runtime code, we'll declare variables that should be available on the global scope of the lambda to keep -// TypeScript type checking happy. -let console: any - -function createLambda() { - // TODO[pulumi/lumi#175] Currently, we can only capture local variables, not module scope variables, - // so we keep this inside a helper function. - let hello = "Hello, world!" - let num = 3 - let obj = { x: 42 } - let mus = music - - let lambda = new aws.serverless.Function( - "mylambda", - [aws.iam.AWSLambdaFullAccess], - (event, context, callback) => { - console.log(hello); - console.log(obj.x); - console.log("Music table hash key is: " + mus.hashKey); - console.log("Invoked function: " + context.invokedFunctionArn); - callback(null, "Succeeed with " + context.getRemainingTimeInMillis() + "ms remaining."); - } - ); - return lambda; -} - -let lambda = createLambda(); +let hello = "Hello, world!" +let lambda = new aws.serverless.Function( + "mylambda", + [aws.iam.AWSLambdaFullAccess], + (event, context, callback) => { + console.log(hello); + console.log("Music table hash key is: " + music.hashKey); + console.log("Invoked function: " + context.invokedFunctionArn); + callback(null, "Succeeed with " + context.getRemainingTimeInMillis() + "ms remaining."); + } +); let api = new aws.serverless.API("frontend") api.route("GET", "/bambam", lambda) diff --git a/examples/scenarios/aws/serverless/package.json b/examples/scenarios/aws/serverless/package.json index 6f2628e87..b1cc07273 100644 --- a/examples/scenarios/aws/serverless/package.json +++ b/examples/scenarios/aws/serverless/package.json @@ -9,6 +9,7 @@ "typescript": "^2.1.4" }, "peerDependencies": { + "@lumi/lumi": "*", "@lumi/aws": "*" } } diff --git a/examples/scenarios/mantle/gh-cicd/index.ts b/examples/scenarios/mantle/gh-cicd/index.ts index 0d4091639..e27169877 100644 --- a/examples/scenarios/mantle/gh-cicd/index.ts +++ b/examples/scenarios/mantle/gh-cicd/index.ts @@ -13,11 +13,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* tslint:disable: ordered-imports */ - +import * as slack from "@slack/client"; import {builders, providers} from "./cicd"; import * as github from "./github"; -import * as slack from "@slack/client"; // On pushes or PR merges, // - In master, build and deploy the bits to production. diff --git a/lib/aws/pack/serverless/api.ts b/lib/aws/pack/serverless/api.ts index 0a399198b..0b8dcdcb8 100644 --- a/lib/aws/pack/serverless/api.ts +++ b/lib/aws/pack/serverless/api.ts @@ -78,7 +78,7 @@ function createPathSpec(lambdaARN: string): SwaggerOperation { } function createSourceARN(region: string, account: string, apiid: string, functionName: string): string { - return "arn:aws:execute-api:"+region+":"+account+":"+apiid+"/*/*/"+ functionName; + return "arn:aws:execute-api:" + region + ":" + account + ":" + apiid + "/*/*/" + functionName; } // API is a higher level abstraction for working with AWS APIGateway reources. @@ -117,9 +117,8 @@ export class API { default: throw new Error("Method not supported: " + method); } -<<<<<<< HEAD let apiName = ""; - if(this.api.apiName !== undefined) { + if (this.api.apiName !== undefined) { apiName = this.api.apiName; } let invokePermission = new Permission(this.apiName + "_invoke_" + sha1hash(method + path), { @@ -129,9 +128,6 @@ export class API { sourceARN: createSourceARN("us-east-1", "490047557317", apiName, "webapi-test-func"), }); // TODO[pulumi/lumi#90]: Once we suport output properties, we can use `lambda.lambda.arn` as input -======= - // TODO[pulumi/lumi#90]: Once we suport output properties, we can use `lambda.lambda.arn` as input ->>>>>>> 13dbcdbafc96be49e509c618194cd649ba6d0817 // to constructing this apigateway lambda invocation uri. // this.swaggerSpec.paths[path][swaggerMethod] = createPathSpec(lambda.lambda.arn); this.swaggerSpec.paths[path][swaggerMethod] = createPathSpec( diff --git a/lib/aws/pack/serverless/function.ts b/lib/aws/pack/serverless/function.ts index 59578fb4a..0121e8fa2 100644 --- a/lib/aws/pack/serverless/function.ts +++ b/lib/aws/pack/serverless/function.ts @@ -13,12 +13,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* tslint:disable: ordered-imports align*/ import { AssetArchive, String } from "@lumi/lumi/asset"; -import { serializeClosure, jsonStringify } from "@lumi/lumi/runtime"; +import { jsonStringify, serializeClosure} from "@lumi/lumi/runtime"; +import { Role } from "../iam/role"; import { Function as LambdaFunction } from "../lambda/function"; import { ARN } from "../types"; -import { Role } from "../iam/role"; // Context is the shape of the context object passed to a Function callback. export interface Context { @@ -56,7 +55,7 @@ export class Function { public role: Role; constructor(name: string, policies: ARN[], - func: (event: any, context: Context, callback: (error: any, result: any) => void) => any) { + func: (event: any, context: Context, callback: (error: any, result: any) => void) => any) { if (name === undefined) { throw new Error("Missing required resource name"); diff --git a/lib/lumi/asset/asset.ts b/lib/lumi/asset/asset.ts index 9b303e68f..27d814ff3 100644 --- a/lib/lumi/asset/asset.ts +++ b/lib/lumi/asset/asset.ts @@ -13,12 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* tslint:disable:no-empty */ - // Asset represents a blob of text or data that is managed as a first class entity. export abstract class Asset { - constructor() { - } } // Blob is a kind of asset produced from an in-memory blob represented as a byte array. diff --git a/lib/lumi/resource.ts b/lib/lumi/resource.ts index c66faae40..93d0272ea 100644 --- a/lib/lumi/resource.ts +++ b/lib/lumi/resource.ts @@ -12,10 +12,8 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -/* tslint:disable:no-empty*/ + // Resource represents a class whose CRUD operations are implemented by a provider plugin. export abstract class Resource { - constructor() { - } } diff --git a/lib/lumijs/Lumi.yaml b/lib/lumijs/Lumi.yaml index afc6be9d9..5d026a381 100644 --- a/lib/lumijs/Lumi.yaml +++ b/lib/lumijs/Lumi.yaml @@ -1,3 +1,5 @@ name: lumijs description: The LumiJS runtime library. +dependencies: + lumi: "*" diff --git a/lib/lumijs/lib/console.ts b/lib/lumijs/lib/console.ts new file mode 100644 index 000000000..1c3f1e63f --- /dev/null +++ b/lib/lumijs/lib/console.ts @@ -0,0 +1,25 @@ +// Licensed to Pulumi Corporation ("Pulumi") under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// Pulumi licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { printf } from "@lumi/lumi/runtime" + +export class Console { + log(message: any) { + printf(message); + printf("\n"); + } +} + +export let console = new Console(); diff --git a/lib/lumijs/lib/index.ts b/lib/lumijs/lib/index.ts index 8ccf7b659..95ca7f984 100644 --- a/lib/lumijs/lib/index.ts +++ b/lib/lumijs/lib/index.ts @@ -17,4 +17,5 @@ export * from "./errors"; export * from "./types"; +export * from "./console"; diff --git a/lib/mantle/arch/clouds/index.ts b/lib/mantle/arch/clouds/index.ts index 254d91eea..b25eec2db 100644 --- a/lib/mantle/arch/clouds/index.ts +++ b/lib/mantle/arch/clouds/index.ts @@ -13,12 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* tslint:disable: variable-name */ + // The available cloud providers. -export const AWS = "aws"; // Amazon Web Services. -export const GCP = "gcp"; // Google Cloud Platform. -export const Azure = "azure"; // Microsoft Azure. -export const VMWare = "vmware"; // VMWare vSphere, etc. +export const aws = "aws"; // Amazon Web Services. +export const gcp = "gcp"; // Google Cloud Platform. +export const azure = "azure"; // Microsoft Azure. +export const vmware = "vmware"; // VMWare vSphere, etc. diff --git a/lib/mantle/arch/index.ts b/lib/mantle/arch/index.ts index dd469aa20..4638986ce 100644 --- a/lib/mantle/arch/index.ts +++ b/lib/mantle/arch/index.ts @@ -13,12 +13,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* tslint:disable:ordered-imports */ - export * from "./arch"; - import * as clouds from "./clouds"; -import * as schedulers from "./schedulers"; import * as runtimes from "./runtimes"; +import * as schedulers from "./schedulers"; export {clouds, schedulers, runtimes}; diff --git a/lib/mantle/arch/runtimes/index.ts b/lib/mantle/arch/runtimes/index.ts index 4b691d00a..04d194b1c 100644 --- a/lib/mantle/arch/runtimes/index.ts +++ b/lib/mantle/arch/runtimes/index.ts @@ -13,15 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* tslint:disable:variable-name */ - // The available language runtimes. - -export const NodeJS = "nodejs"; -export const Python = "python"; +export const nodejs = "nodejs"; +export const python = "python"; export let ext: {[lang: string]: string} = { - NodeJS: ".js", - Python: ".py", + nodejs: ".js", + python: ".py", }; diff --git a/lib/mantle/arch/schedulers/index.ts b/lib/mantle/arch/schedulers/index.ts index 21bd67b28..c3be9167f 100644 --- a/lib/mantle/arch/schedulers/index.ts +++ b/lib/mantle/arch/schedulers/index.ts @@ -13,14 +13,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* tslint:disable:variable-name */ - // The available container scheduler/runtimes. - -export const Swarm = "swarm"; // Docker Swarm. -export const Kubernetes = "kubernetes"; // Kubernetes. -export const Mesos = "mesos"; // Apache Mesos. -export const ECS = "ecs"; // Amazon Elastic Container Service (only valid for AWS clouds). -export const GKE = "gke"; // Google Container Engine (only valid for GCP clouds). -export const ACS = "acs"; // Microsoft Azure Container Service (only valid for Azure). +export const swarm = "swarm"; // Docker Swarm. +export const kubernetes = "kubernetes"; // Kubernetes. +export const mesos = "mesos"; // Apache Mesos. +export const ecs = "ecs"; // Amazon Elastic Container Service (only valid for AWS clouds). +export const gke = "gke"; // Google Container Engine (only valid for GCP clouds). +export const acs = "acs"; // Microsoft Azure Container Service (only valid for Azure). diff --git a/lib/mantle/func/function.ts b/lib/mantle/func/function.ts index c3f30851a..41d5caeb6 100644 --- a/lib/mantle/func/function.ts +++ b/lib/mantle/func/function.ts @@ -13,14 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -/* tslint:disable:ordered-imports */ - -import * as arch from "../arch"; -import * as config from "../config"; -import * as runtime from "../runtime"; import * as aws from "@lumi/aws"; import * as kubefission from "@lumi/kubefission"; import {asset} from "@lumi/lumi"; +import * as arch from "../arch"; +import * as config from "../config"; +import * as runtime from "../runtime"; // Function is a cross-cloud function abstraction whose source code is taken from a string, file, or network asset. // For example, `https://gist.github.com/pulumi/fe8a5ae322ffe63fac90535eb554237f` will use a Gist published on GitHub, @@ -48,16 +46,16 @@ export class Function { // initCloudResources sets up the right resources for the given cloud and scheduler target. private initCloudResources(): any { let target: arch.Arch = config.requireArch(); - if (target.scheduler === arch.schedulers.Kubernetes) { + if (target.scheduler === arch.schedulers.kubernetes) { return this.initKubernetesResources(); } else { switch (target.cloud) { - case arch.clouds.AWS: + case arch.clouds.aws: return this.initAWSResources(); - case arch.clouds.GCP: + case arch.clouds.gcp: return this.initGCPResources(); - case arch.clouds.Azure: + case arch.clouds.azure: return this.initAzureResources(); default: throw new Error("Unsupported target cloud: " + target.cloud); diff --git a/pkg/compiler/binder/freevars.go b/pkg/compiler/binder/freevars.go new file mode 100644 index 000000000..2a4819a71 --- /dev/null +++ b/pkg/compiler/binder/freevars.go @@ -0,0 +1,107 @@ +// Licensed to Pulumi Corporation ("Pulumi") under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// Pulumi licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package binder + +import ( + "github.com/pulumi/lumi/pkg/compiler/ast" + "github.com/pulumi/lumi/pkg/tokens" + "github.com/pulumi/lumi/pkg/util/contract" +) + +// FreeVars computes the free variables referenced inside a function body. +// The free variables for a function will be either simple identifier tokens or tokens +// referencing module-scope variables. +func FreeVars(fnc ast.Function) []tokens.Token { + visitor := &freeVarsVisitor{ + freeVars: map[tokens.Token]bool{}, + } + + ast.Walk(visitor, fnc) + + params := fnc.GetParameters() + if params != nil { + for _, lv := range *params { + visitor.removeLocalVariable(lv) + } + } + + var vars []tokens.Token + for k := range visitor.freeVars { + vars = append(vars, k) + } + return vars +} + +type freeVarsVisitor struct { + freeVars map[tokens.Token]bool +} + +var _ ast.Visitor = (*freeVarsVisitor)(nil) + +func (visitor *freeVarsVisitor) Visit(node ast.Node) ast.Visitor { + return visitor +} + +// We walk the AST and process each node after visiting it in depth first order. There are two cases we care about: +// 1) After visiting a leaf node which is a reference to a local variable (`n.Object == nil``), we add it to our set. +// 2) After visiting a LocalVariableDeclaration or a Lambda, we remove the declared variables from our set. +func (visitor *freeVarsVisitor) After(node ast.Node) { + switch n := node.(type) { + case *ast.LoadLocationExpression: + if n.Object == nil { + visitor.addToken(n.Name.Tok) + } + case *ast.LoadDynamicExpression: + if n.Object == nil { + switch e := n.Name.(type) { + case *ast.StringLiteral: + visitor.addToken(tokens.Token(e.Value)) + default: + contract.Failf("expected LoadDynamicExpression with Object == nil to have a StringLiteral expression") + } + } + case *ast.TryLoadDynamicExpression: + if n.Object == nil { + switch e := n.Name.(type) { + case *ast.StringLiteral: + visitor.addToken(tokens.Token(e.Value)) + default: + contract.Failf("expected LoadDynamicExpression with Object == nil to have a StringLiteral expression") + } + } + case *ast.LambdaExpression: + if n.Parameters != nil { + for _, param := range *n.Parameters { + visitor.removeLocalVariable(param) + } + } + case *ast.Block: + for _, stmt := range n.Statements { + switch s := stmt.(type) { + case *ast.LocalVariableDeclaration: + visitor.removeLocalVariable(s.Local) + } + } + } +} + +func (visitor *freeVarsVisitor) addToken(tok tokens.Token) { + visitor.freeVars[tok] = true +} + +func (visitor *freeVarsVisitor) removeLocalVariable(lv *ast.LocalVariable) { + delete(visitor.freeVars, tokens.Token(lv.Name.Ident)) +} diff --git a/pkg/compiler/binder/freevars_test.go b/pkg/compiler/binder/freevars_test.go new file mode 100644 index 000000000..9503fa9b9 --- /dev/null +++ b/pkg/compiler/binder/freevars_test.go @@ -0,0 +1,192 @@ +// Licensed to Pulumi Corporation ("Pulumi") under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// Pulumi licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package binder + +import ( + "testing" + + "github.com/pulumi/lumi/pkg/compiler/ast" + "github.com/pulumi/lumi/pkg/compiler/types" + "github.com/pulumi/lumi/pkg/tokens" + "github.com/stretchr/testify/assert" +) + +func makeLocalVariable(name string) *ast.LocalVariable { + return &ast.LocalVariable{ + DefinitionNode: ast.DefinitionNode{ + Name: &ast.Identifier{ + Ident: tokens.Name(name), + }, + }, + VariableNode: ast.VariableNode{ + Type: &ast.TypeToken{ + Tok: types.Object.TypeToken(), + }, + }, + } +} + +func expressionRef(expr ast.Expression) *ast.Expression { + return &expr +} + +func TestFreeVars_Parameter(t *testing.T) { + // function(foo) foo + fun := ast.ModuleMethod{ + FunctionNode: ast.FunctionNode{ + Parameters: &[]*ast.LocalVariable{ + makeLocalVariable("foo"), + }, + Body: &ast.ExpressionStatement{ + Expression: &ast.LoadLocationExpression{ + Name: &ast.Token{ + Tok: tokens.Token("foo"), + }, + }, + }, + }, + } + freeVars := FreeVars(&fun) + assert.Len(t, freeVars, 0, "expected no free variables") +} + +func TestFreeVars_Dynamic(t *testing.T) { + // function(foo) foo + fun := ast.ModuleMethod{ + FunctionNode: ast.FunctionNode{ + Parameters: &[]*ast.LocalVariable{}, + Body: &ast.ExpressionStatement{ + Expression: &ast.LoadDynamicExpression{ + Name: &ast.StringLiteral{ + Value: "foo", + }, + }, + }, + }, + } + freeVars := FreeVars(&fun) + assert.Len(t, freeVars, 1, "expected one free variable") + assert.Equal(t, tokens.Name("foo"), freeVars[0].Name()) +} + +func TestFreeVars_LocalVariable(t *testing.T) { + // function(foo) { var bar; foo; bar; baz; } + fun := ast.ModuleMethod{ + FunctionNode: ast.FunctionNode{ + Parameters: &[]*ast.LocalVariable{ + makeLocalVariable("foo"), + }, + Body: &ast.Block{ + Statements: []ast.Statement{ + &ast.LocalVariableDeclaration{ + Local: makeLocalVariable("bar"), + }, + &ast.ExpressionStatement{ + Expression: &ast.LoadLocationExpression{ + Name: &ast.Token{ + Tok: tokens.Token("foo"), + }, + }, + }, + &ast.ExpressionStatement{ + Expression: &ast.LoadLocationExpression{ + Name: &ast.Token{ + Tok: tokens.Token("bar"), + }, + }, + }, + &ast.ExpressionStatement{ + Expression: &ast.TryLoadDynamicExpression{ + Name: &ast.StringLiteral{ + Value: "baz", + }, + }, + }, + }, + }, + }, + } + freeVars := FreeVars(&fun) + assert.Len(t, freeVars, 1, "expected one free variable") + assert.Equal(t, tokens.Name("baz"), freeVars[0].Name()) +} + +func TestFreeVars_Member(t *testing.T) { + // function(foo) foo.bar + fun := ast.ModuleMethod{ + FunctionNode: ast.FunctionNode{ + Parameters: &[]*ast.LocalVariable{ + makeLocalVariable("foo"), + }, + Body: &ast.ExpressionStatement{ + Expression: &ast.LoadLocationExpression{ + Object: expressionRef(&ast.LoadLocationExpression{ + Name: &ast.Token{ + Tok: tokens.Token("foo"), + }, + }), + Name: &ast.Token{ + Tok: tokens.Token("bar"), + }, + }, + }, + }, + } + freeVars := FreeVars(&fun) + assert.Len(t, freeVars, 0, "expected no free variables") +} + +func TestFreeVars_Lambda(t *testing.T) { + // function(foo) ((bar) => bar)(foo) + fun := ast.ModuleMethod{ + FunctionNode: ast.FunctionNode{ + Parameters: &[]*ast.LocalVariable{ + makeLocalVariable("foo"), + }, + Body: &ast.ExpressionStatement{ + Expression: &ast.InvokeFunctionExpression{ + Function: &ast.LambdaExpression{ + FunctionNode: ast.FunctionNode{ + Parameters: &[]*ast.LocalVariable{ + makeLocalVariable("bar"), + }, + Body: &ast.ExpressionStatement{ + Expression: &ast.LoadLocationExpression{ + Name: &ast.Token{ + Tok: tokens.Token("bar"), + }, + }, + }, + }, + }, + CallExpressionNode: ast.CallExpressionNode{ + Arguments: &[]*ast.CallArgument{ + &ast.CallArgument{ + Expr: &ast.LoadLocationExpression{ + Name: &ast.Token{ + Tok: tokens.Token("foo"), + }, + }, + }, + }, + }, + }, + }, + }, + } + freeVars := FreeVars(&fun) + assert.Len(t, freeVars, 0, "expected no free variables") +} diff --git a/pkg/eval/eval.go b/pkg/eval/eval.go index e93ca450e..7da34f521 100644 --- a/pkg/eval/eval.go +++ b/pkg/eval/eval.go @@ -1730,22 +1730,23 @@ func (e *evaluator) evalLoadDynamicCore(node ast.Node, objexpr *ast.Expression, }, nil } -func (e *evaluator) getDynamicNameAddr(key tokens.Name, lval bool) *rt.Pointer { - var pv *rt.Pointer - - // If there's no object, look in the current localsment. - pkey := rt.PropertyKey(key) - globals := e.getModuleGlobals(e.ctx.Currmodule) - if loc := e.locals.Lookup(key); loc != nil { - pv = e.locals.GetValueAddr(loc, true) // create a slot, we know the declaration exists. - } else { - // If it didn't exist in the lexical scope, check the module's globals. - pv = globals.Properties().GetAddr(pkey) // look for a global by this name, but don't allocate one. +func getDynamicNameAddrCore(locals rt.Environment, globals *rt.Object, key tokens.Name) *rt.Pointer { + if loc := locals.Lookup(key); loc != nil { + return locals.GetValueAddr(loc, true) // create a slot, we know the declaration exists. } + // If it didn't exist in the lexical scope, check the module's globals. + pkey := rt.PropertyKey(key) + return globals.Properties().GetAddr(pkey) // look for a global by this name, but don't allocate one. +} - // Finally, if neither of those existed, and this is the target of a load, allocate a slot. +func (e *evaluator) getDynamicNameAddr(key tokens.Name, lval bool) *rt.Pointer { + globals := e.getModuleGlobals(e.ctx.Currmodule) + pv := getDynamicNameAddrCore(e.locals, globals, key) + + // If not found and this is the target of a load, allocate a slot. if pv == nil && lval { if e.fnc != nil && e.fnc.SpecialModInit() && e.locals.Activation() { + pkey := rt.PropertyKey(key) pv = globals.Properties().GetInitAddr(pkey) } else { loc := symbols.NewSpecialVariableSym(key, types.Dynamic) @@ -1870,7 +1871,8 @@ func (e *evaluator) evalLambdaExpression(node *ast.LambdaExpression) (*rt.Object // To create a lambda object we will simply produce a function object that can invoke it. Lambdas also uniquely // capture the current environment, including the this variable. sig := e.ctx.RequireType(node).(*symbols.FunctionType) - obj := rt.NewFunctionObjectFromLambda(node, sig, e.locals) + moduleObject := e.getModuleGlobals(e.ctx.Currmodule) + obj := rt.NewFunctionObjectFromLambda(node, sig, e.locals, moduleObject) return obj, nil } diff --git a/pkg/eval/intrinsics_impl.go b/pkg/eval/intrinsics_impl.go index 9919d34ac..93afc6ad2 100644 --- a/pkg/eval/intrinsics_impl.go +++ b/pkg/eval/intrinsics_impl.go @@ -19,14 +19,15 @@ import ( "crypto/sha1" "encoding/hex" "fmt" - "sort" "strconv" "strings" "github.com/pulumi/lumi/pkg/compiler/ast" + "github.com/pulumi/lumi/pkg/compiler/binder" "github.com/pulumi/lumi/pkg/compiler/symbols" "github.com/pulumi/lumi/pkg/compiler/types" "github.com/pulumi/lumi/pkg/eval/rt" + "github.com/pulumi/lumi/pkg/tokens" "github.com/pulumi/lumi/pkg/util/contract" ) @@ -108,21 +109,24 @@ func serializeClosure(intrin *rt.Intrinsic, e *evaluator, this *rt.Object, args return e.NewException(intrin.Tree(), "Expected argument 'func' to be a lambda expression.") } - // TODO[pulumi/lumi#177]: We are using the full environment available at execution time here, we should - // instead capture only the free variables referenced in the function itself. - // Insert environment variables into a PropertyMap with stable ordering envPropMap := rt.NewPropertyMap() - slots := stub.Env.Slots() - var keys []*symbols.LocalVariable - for key := range slots { - keys = append(keys, key) - } - sort.SliceStable(keys, func(i, j int) bool { - return keys[i].Name() < keys[j].Name() - }) - for _, key := range keys { - envPropMap.Set(rt.PropertyKey(key.Name()), slots[key].Obj()) + for _, tok := range binder.FreeVars(stub.Func) { + var name tokens.Name + contract.Assertf(tok.Simple() || (tok.HasModule() && tok.HasModuleMember() && !tok.HasClassMember()), + "Expected free variable to be simple name or reference to top-level module name") + if tok.Simple() { + name = tok.Name() + } else { + name = tokens.Name(tok.ModuleMember().Name()) + } + pv := getDynamicNameAddrCore(stub.Env, stub.Module, name) + if pv != nil { + envPropMap.Set(rt.PropertyKey(name), pv.Obj()) + } + // Else the variable was not found, so we skip serializing it. + // This will be true for references to globals which are not known to Lumi but + // will be available within the runtime environment. } envObj := e.alloc.New(intrin.Tree(), types.Dynamic, envPropMap, nil) diff --git a/pkg/eval/rt/object.go b/pkg/eval/rt/object.go index 6930c94a0..dd6319695 100644 --- a/pkg/eval/rt/object.go +++ b/pkg/eval/rt/object.go @@ -452,21 +452,23 @@ func NewFunctionObjectFromSymbol(fnc symbols.Function, this *Object) *Object { } // NewFunctionObjectFromLambda creates a new function object with very specific underlying parts. -func NewFunctionObjectFromLambda(fnc ast.Function, sig *symbols.FunctionType, env Environment) *Object { +func NewFunctionObjectFromLambda(fnc ast.Function, sig *symbols.FunctionType, env Environment, module *Object) *Object { return NewFunctionObject(FuncStub{ - Func: fnc, - Sig: sig, - Env: env, + Func: fnc, + Sig: sig, + Env: env, + Module: module, }) } // FuncStub is a stub that captures a symbol plus an optional instance 'this' object. type FuncStub struct { - Func ast.Function // the function whose body AST to evaluate. - Sym symbols.Function // an optional function symbol that this AST belongs to. - Sig *symbols.FunctionType // the function type representing this function's signature. - This *Object // an optional "this" pointer to bind when invoking this function. - Env Environment // an optional environment to evaluate this function inside. + Func ast.Function // the function whose body AST to evaluate. + Sym symbols.Function // an optional function symbol that this AST belongs to. + Sig *symbols.FunctionType // the function type representing this function's signature. + This *Object // an optional "this" pointer to bind when invoking this function. + Env Environment // an optional environment to evaluate this function inside. + Module *Object // an optional module object to use for module variable lookups inside this function. } // NewPointerObject allocates a new pointer-like object that wraps the given reference. @@ -641,11 +643,12 @@ func adjustPointerForThis(parent *Object, this *Object, prop *Pointer) *Pointer stub := value.FunctionValue() contract.Assert(stub.This == parent) value = NewFunctionObject(FuncStub{ - Func: stub.Func, - Sym: stub.Sym, - Sig: stub.Sig, - This: this, - Env: stub.Env, + Func: stub.Func, + Sym: stub.Sym, + Sig: stub.Sig, + This: this, + Env: stub.Env, + Module: stub.Module, }) prop = NewPointer(value, prop.Readonly(), prop.Getter(), prop.Setter()) case *symbols.ComputedType: @@ -684,7 +687,7 @@ func (intrin *Intrinsic) SpecialModInit() bool { return false } func (intrin *Intrinsic) Tree() diag.Diagable { return intrin.node } func (intrin *Intrinsic) Function() ast.Function { return intrin.node } func (intrin *Intrinsic) Signature() *symbols.FunctionType { return intrin.sig } -func (intrin *Intrinsic) String() string { return string(intrin.Name()) } +func (intrin *Intrinsic) String() string { return string(intrin.Token()) } func (intrin *Intrinsic) UnderlyingSymbol() symbols.Function { return intrin.fnc } diff --git a/pkg/graph/dotconv/print.go b/pkg/graph/dotconv/print.go index 13a586ca8..0f01c1ac9 100644 --- a/pkg/graph/dotconv/print.go +++ b/pkg/graph/dotconv/print.go @@ -28,8 +28,8 @@ import ( "github.com/pulumi/lumi/pkg/util/contract" ) +// Print prints a LumiGL graph. func Print(g graph.Graph, w io.Writer) error { - var err error // Allocate a new writer. In general, we will ignore write errors throughout this function, for simplicity, opting // instead to return the result of flushing the buffer at the end, which is generally latching. diff --git a/pkg/resource/asset.go b/pkg/resource/asset.go index 82b2cd387..9ddf1fbb2 100644 --- a/pkg/resource/asset.go +++ b/pkg/resource/asset.go @@ -346,12 +346,11 @@ func (a Archive) openURLStream(url *url.URL) (io.ReadCloser, error) { // Bytes fetches the archive contents as a byte slices. This is almost certainly the least efficient way to deal with // the underlying streaming capabilities offered by assets and archives, but can be used in a pinch to interact with // APIs that demand []bytes. -func (a Archive) Bytes(format ArchiveFormat) []byte { +func (a Archive) Bytes(format ArchiveFormat) ([]byte, error) { var data bytes.Buffer - err := a.Archive(format, &data) - contract.Assert(err == nil) - - return data.Bytes() + var err error + err = a.Archive(format, &data) + return data.Bytes(), err } // Archive produces a single archive stream in the desired format. It prefers to return the archive with as little diff --git a/pkg/resource/plugin.go b/pkg/resource/plugin.go index ef9d5c034..9cf3de12c 100644 --- a/pkg/resource/plugin.go +++ b/pkg/resource/plugin.go @@ -95,13 +95,13 @@ func newPlugin(ctx *Context, bins []string, prefix string) (*plugin, error) { var port string b := make([]byte, 1) for { - n, stderr := plug.Stdout.Read(b) - if stderr != nil { + n, readerr := plug.Stdout.Read(b) + if readerr != nil { plug.Proc.Kill() if port == "" { - return nil, errors.Wrapf(stderr, "could not read plugin [%v] stdout", foundbin) + return nil, errors.Wrapf(readerr, "could not read plugin [%v] stdout", foundbin) } - return nil, errors.Wrapf(stderr, "failure reading plugin [%v] stdout (read '%v')", foundbin, port) + return nil, errors.Wrapf(readerr, "failure reading plugin [%v] stdout (read '%v')", foundbin, port) } if n > 0 && b[0] == '\n' { break diff --git a/pkg/tools/lumidl/gen.go b/pkg/tools/lumidl/gen.go index 75e0768a5..bf4ee71d7 100644 --- a/pkg/tools/lumidl/gen.go +++ b/pkg/tools/lumidl/gen.go @@ -37,7 +37,6 @@ func writefmtln(w *bufio.Writer, msg string, args ...interface{}) { func emitHeaderWarning(w *bufio.Writer) { writefmtln(w, "// *** WARNING: this file was generated by the Lumi IDL Compiler (LUMIDL). ***") writefmtln(w, "// *** Do not edit by hand unless you're certain you know what you are doing! ***") - writefmtln(w, "/* tslint:disable:ordered-imports variable-name */") writefmtln(w, "") } diff --git a/pkg/tools/lumidl/gen_pack.go b/pkg/tools/lumidl/gen_pack.go index 2aa3f5c79..352eac91b 100644 --- a/pkg/tools/lumidl/gen_pack.go +++ b/pkg/tools/lumidl/gen_pack.go @@ -126,6 +126,7 @@ func (g *PackGenerator) emitFileContents(file string, body string) error { // Emit a header into the file. emitHeaderWarning(w) + writefmtln(w, "/* tslint:disable:ordered-imports variable-name */") // If there are any resources, import the Lumi package. if g.FileHadRes { diff --git a/pkg/util/cmdutil/log.go b/pkg/util/cmdutil/log.go index f1753d3b5..7b8c0d707 100644 --- a/pkg/util/cmdutil/log.go +++ b/pkg/util/cmdutil/log.go @@ -38,15 +38,10 @@ func InitLogging(logToStderr bool, verbose int, logFlow bool) { flag.Parse() if logToStderr { err := flag.Lookup("logtostderr").Value.Set("true") - if err != nil { - contract.Assert(err != nil) - } - + contract.Assert(err != nil) } if verbose > 0 { err := flag.Lookup("v").Value.Set(strconv.Itoa(verbose)) - if err != nil { - contract.Assert(err != nil) - } + contract.Assert(err != nil) } } diff --git a/pkg/workspace/workspace.go b/pkg/workspace/workspace.go index e777b5a08..3ef4964b4 100644 --- a/pkg/workspace/workspace.go +++ b/pkg/workspace/workspace.go @@ -178,11 +178,6 @@ func (w *workspace) DepCandidates(dep pack.PackageURL) []string { return cands } -// namePath just cleans a name and makes sure it's appropriate to use as a path. -func namePath(nm tokens.Name) string { //nolint - return stringNamePath(string(nm)) -} - // qnamePath just cleans a name and makes sure it's appropriate to use as a path. func qnamePath(nm tokens.QName) string { return stringNamePath(string(nm)) diff --git a/tslint.json b/tslint.json index e80ab714b..cfa521f5e 100644 --- a/tslint.json +++ b/tslint.json @@ -120,5 +120,6 @@ "check-separator", "check-type" ] + } } \ No newline at end of file