Declare a global variable in boo - boo

As far as I can tell from the website, the following code should compile to a DLL with a top-level property Version:
namespace MyLibrary
[Module]
class MainClass:
public static Version as string
static def constructor():
Version = "0.1"
This compiles, but if I then enter these commands into booish:
import MyLibrary
print (Version)
then I get "ERROR: Unknown identifier: 'Version'".
Presumably this code worked in an earlier version of the language. I am using 0.9.4.9. What is the correct way to achieve this effect?
(I've noticed that there is an implicit static class MyVersionModule in which top-level static methods get placed, but I don't know how to add properties to this either).

In .net there is no way to have methods or fields that are not actually members of a class. Boo hides this somewhat by having the implicit class for the main file in the module (as you noticed) but when importing you still need to access it as a member.
For statics you have to first reference the type then the member so in your example printing the version would be like this:
import MyLibrary
print (MainClass.Version)
Of course this isn't the 'correct' way to store version information in .net though, which is to use assembly level attributes instead. That would look more like this:
[assembly: System.Reflection.AssemblyVersion("1.0")]
namespace MyLibrary
[Module]
class MainClass:
pass
Then getting the version you would do using reflection, there are a couple of ways to get the assembly but the easiest is to get the Type then it's assembly:
import System
import System.Reflection
import MyLibrary
atts = typeof(MainClass).Assembly \
.GetCustomAttributes(typeof(AssemblyVersionAttribute), false)
version = (atts[0] as AssemblyVersionAttribute).Version
print(version)

Related

How to import a class from a Jenkins Shared Library into the pipeline

I was using some global methods in the /var directory of the shared library, and everything worked fine. Now I need to keep the state of the process, so I'm writting a groovy class.
Basically I have a class called 'ClassTest.groovy' in '/src' which is something like this;
class ClassTest {
String testString
def method1() { ... }
def method2() { ... }
}
and at the begining of the pipeline
library 'testlibrary#'
import ClassTest
with result:
WorkflowScript: 2: unable to resolve class ClassTest #line 2, column 1.
import ClassTest
before, I was just goind
library 'testlibrary#' _
and using the methods as
script {
libraryTest.method1()
...
libraryTest.method2()
}
where the methods were in a file '/var/libraryTest.groovy' and everything worked. So I know that the shared library is there, but I'm confused with the way groovy / Jenkins handle classes / shared libraries.
What's the correct way to import a class? I cannot find a simple example (with groovy file, file structure and pipeline) in the documentation.
EDIT:
I moved the file to 'src/com/company/ClassTest.groovy' and modified the pipeline as
#Library('testlibrary#') import com.company.ClassTest
def notification = new ClassTest()
but now the error is
unexpected token: package # line 2
the first two lines of the groovy file are:
// src/com/company/ClassTest.groovy
package com.company;
So far this is what I've found.
To load the library in the pipeline I used:
#Library('testlibrary#') import com.company.ClassTest
def notification = new ClassTest()
In the class file, no package instruction. I guess that I don't need one because I don't have any other files or classes, so I don't really need a package. Also, I got an error when using the same name for the class and for the file where the class is. The error specifically complained and asked for one of them to be changed. I guess this two things are related to Jenkins.
That works, and the library is loaded.
(Maybe it can help someone else)
I was having the same issue.
Once I added a package-info.java inside the folder com/lib/, containing
/**
* com.lib package
*/
package com.lib;
and adding package com.lib at the first line of each file, it started to work.
I had the same problem.
After some trial and error with the docs of Jenkins.(https://www.jenkins.io/doc/book/pipeline/shared-libraries/#using-libraries)
I found that when I wanted to import a class from the shared library I have, I needed to do it like this:
//thanks to '_', the classes are imported automatically.
// MUST have the '#' at the beginning, other wise it will not work.
#Library('my-shared-library#BRANCH') _
// only by calling them you can tell if they exist or not.
def exampleObject = new example.GlobalVars()
// then call methods or attributes from the class.
exampleObject.runExample()

implicit TableHelper with 2.12.1?

Am I completely missing something? Trying to build the absolute most basic project with phantom is causing this error:
could not find implicit value for parameter helper: com.outworkers.phantom.macros.TableHelper[models.Accounts,models.Account]
build.sbt is using version 2.12.1.
Account.scala is this:
package models
import com.outworkers.phantom.dsl._
case class Account(username: String)
abstract class Accounts extends Table[Accounts, Account] with RootConnector {
object username extends StringColumn with PrimaryKey
}
I thought I was following the quickstart documentation, but I cannot get this to compile at all. Meanwhile, the Play-Cassandra project compiles just fine.
Writing here for future Googlers, this is because your schema does not define a PartitionKey, which is a requirement. The compiler should issue a warning when the macro is summoned.
package models
import com.outworkers.phantom.dsl._
case class Account(username: String)
abstract class Accounts extends Table[Accounts, Account] {
object username extends StringColumn with PartitionKey
}
On a side note, extending Table already brings in RootConnector, so you do not need to explicitly extend it again, as it was the case in older versions of phantom using CassandraTable instead of Table.

Typescript enum, used from implementation and interfaces

I have the following, in CommandEnum.ts:
export enum CommandEnum {
createProject,
renameProject,
hablaBabla
}
in a module which I am able to reference from implementation code, using
import {CommandEnum} from '../server/contracts/CommandEnum'
let x = CommmandEnum.hablaBabla
The enum file is compiled into a javascript function with export logic, in CommandEnum.js.
This now works fine, but I want to reference this enum in my interfaces as well, I try:
/// <reference path="../contracts/CommandEnum.ts" />
namespace ValueTypes {
export interface Command {
type : CommandEnum;
referenceId : string;
}
}
Now, this reference does not import the CommandEnum type, but some of the other combinations of modules / namespace / export default I have tried does. I can get the reference syntax to work, but not the module syntax and the other way around - but not both.
Is this actually possible? Using an enum from a pure definitions interface file seems like a very common scenario. But when the interface is implemented the enum must be available in "function form" and these two models does not seem to combine?
I had the same problem with classes, which I wanted to namespace, .Net-style - which I had to give up. Classes, however, are not referenced in my interfaces - enums are.
I work with node.js and compile to individual files, not a single concated output.
This now works fine, but I want to reference this enum in my interfaces as well
You can move stuff from a module into the global namespace use declare global
E.g. myEnumGlobalDeclare.ts
import {MyEnum as MyEnumModule} from "./myEnum";
declare global {
declare var MyEnum: typeof MyEnumModule;
}
E.g. myEnumGlobalDefine.ts
import {MyEnum as MyEnumModule} from "./myEnum";
MyEnum = MyEnumModule;
Or something similar ^. Of course this means your runtime should support global augmentation e.g. in nodejs you need to use globals and in browsers window.
More
I definitely do not recommend going down this path. Instead create a global types.ts module and just use that everywhere. E.g. alm has this file : https://github.com/alm-tools/alm/blob/master/src/common/types.ts

Use types (interfaces) from other commonjs modules in Visual Studio using TypeScript without having to import that module?

I'm trying to simply use types (interfaces) from other commonjs modules. I'm wondering if there is a way to do this without having to import the module each time I need just the types (no implementation)?
Also to the same point. How would I use commonjs declared module types in projects without compiling with "--module commonjs"? (just to use the types, I'm aware you could do var x = require('x') if you don't care about type safety, but that defeats the purpose of TypeScript)
This seems like a valid use case as one could desire to create a library free from the actual implementation... But as I currently see it, you have to import x = require('x') on the actual implementation, even if I don't need it and already have the definition file.
Is there a way to tell the compiler that it "just exists," similar to how declare works with variables?
Example:
Suppose I have file.ts that I'm not compiling with any module setting (none):
/// <reference path="ExternalCommonJSModule.d.ts" />
export class A {
public foo(bar: ITypeFromExternalCommonJSModule): number {
return bar.x * 2;
}
}
And suppose ExternalCommonJSModule.d.ts looks like this:
declare module "ExternalCommonJSModule" {
export interface ITypeFromExternalCommonJSModule {
x: number;
}
}
(note, this doesn't compile because file.ts isn't compiled with --module commonjs and it doesn't import the implementation of the .d.ts)
I'm wondering if there is a way to do this without having to import the module each time I need just the types (no implementation)
You can put the interfaces in a global module e.g. globals.d.ts and then you would be able to use them throughout the project without importing.
Note: as soon as you global you are severely limiting the shareability of your code and opening yourself to the diamond version dependency problem.

Importing files in the header

I was wondering if I could import a header file, but not include any of that header file's included headers.
Suppose I have Class A that imports Class B. In Class B, I import Class C. Is there any way I can hide Class C from Class A?
No, you cannot do that: once you import a file, all its imports come in as well.
However, if you want to use only ClassA, you can forward-declare it in your own header, instead of importing ClassA's header:
#class ClassA;
Now you can make variables of type ClassA*, use ClassA* as return type or a parameter type, etc. At the same time, dependencies of ClassA's header will not be loaded.
In general, it is a good idea to reduce the number of headers that you import inside your header, for example by moving imports related to implementation (rather than the interface) into the .m file, and using class extensions.

Resources