I give permission for IBM, its customers, partners, and minions, to use JSLint for evil.
dev.hasenj.org/post/3272592502/ibm-and-its-minions

pixel skylines
dirt enthusiast
Cosmic Funnies
Lint Roller? I Barely Know Her
let's talk about Bridgerton tea, my ask is open

No title available
No title available

titsay
Monterey Bay Aquarium
he wasn't even looking at me and he found me
Game of Thrones Daily
will byers stan first human second
No title available

JBB: An Artblog!
🪼
d e v o n
RMH

Product Placement
Alisa U Zemlji Chuda
TVSTRANGERTHINGS

seen from United States
seen from United States

seen from Malaysia
seen from United States
seen from United States
seen from United States
seen from United States

seen from United States
seen from Germany

seen from France
seen from United States

seen from Türkiye

seen from United States

seen from United Kingdom
seen from Malaysia
seen from Malaysia
seen from Germany
seen from Australia
seen from United States
seen from Türkiye
@xtendasy
I give permission for IBM, its customers, partners, and minions, to use JSLint for evil.
dev.hasenj.org/post/3272592502/ibm-and-its-minions
I love stack traces. Not because I love errors, but the moment they occur, stack trace is priceless source of information. For instance in web application the...
A portal on this practice
About how code review can look like using pull requests.
JavaDoc is dead, long live JavaDoc!
Ever wondered how the future of JavaDoc might look like?
How about this: Markdown instead of HTML.
Try it now - in Xtend with these few lines:
@Active(DocProc) annotation Doc { String value } class DocProc implements TransformationParticipant<MutableMemberDeclaration> { override doTransform(List<? extends MutableMemberDeclaration> annotatedTargetElements, extension TransformationContext context) { annotatedTargetElements.filter(MutableAnnotationTarget).forEach [ val annot = findAnnotation(Doc.newTypeReference.type) val markDown = annot.getValue("value") as String val proc = new MarkdownProcessor val html = proc.markdown(markDown) switch (it) { MutableMemberDeclaration: docComment = html } removeAnnotation(annot) ] } }
Result:
Markdown processing powered by markdown.
Map interface implementation for your classes (part 3)
Here's our annotation. You can change the underlying implementation for the view-returning methods as well as the ALL_KEYS visibility:
@Target(TYPE) @Active(MapLikeProcessor) annotation MapLike { Class<? extends Set<?>> customSet = CustomSet String allKeysVisibility = "PUBLIC" }
Our processor is now ready. We switch over keys (see why) to manipulate the right fields, treating null as not present and reset fields to null, false or 0.
class MapLikeProcessor extends AbstractClassProcessor { override doTransform(MutableClassDeclaration it, extension TransformationContext x) { implementedInterfaces = implementedInterfaces + #[Map.newTypeReference(string, object)] val fields = declaredFields val annot = findAnnotation(MapLike.newTypeReference.type) val impl = annot.getValue("customSet") as TypeReference val allKeysVisibleName = annot.getValue("allKeysVisibility") as String val allKeysVisibility = Visibility.valueOf(allKeysVisibleName) addField("ALL_KEYS") [ type = List.newTypeReference(string) visibility = allKeysVisibility static = true final = true initializer = [ '''«toJavaCode(ImmutableList.newTypeReference)».of( «fields.map['''"«simpleName»"'''].join(", ")»)''' ] ] overrideIfNotPresent(x, object, "get", #["key" -> object]) [ ''' switch((String) key) { «FOR f : fields» case "«f.simpleName»": return «f.simpleName»; «ENDFOR» default: return null; } ''' ] overrideIfNotPresent(x, object, "put", #["key" -> string, "value" -> object]) [ ''' Object res; switch((String) key) { «FOR f : fields» case "«f.simpleName»": res = this.«f.simpleName»; this.«f.simpleName» = («f.type») value; return res; «ENDFOR» default: «fail('''"Key not found: " + key''', x)» } ''' ] overrideIfNotPresent(x, primitiveBoolean, "containsKey", #["key" -> object]) [ ''' switch((String) key) { «FOR f : fields» «val res = if(f.type.primitive) "true" else '''this.«f.simpleName» != null'''» case "«f.simpleName»": return «res»; «ENDFOR» default: return false; } ''' ] overrideIfNotPresent(x, primitiveBoolean, "containsValue", #["obj" -> object]) [ ''' «FOR f : fields» «IF f.type.primitive» if(obj instanceof «f.type.wrapperIfPrimitive» && («f.type») obj == this.«f.simpleName») { return true; } «ELSE» if(this.«f.simpleName» == obj || (this.«f.simpleName» != null && this.«f.simpleName».equals(obj))) { return true; } «ENDIF» «ENDFOR» return false; ''' ] overrideIfNotPresent(x, object, "remove", #["key" -> object]) [ ''' Object res; switch((String) key) { «FOR f : fields» case "«f.simpleName»": «IF f.type.primitive» this.«f.simpleName» = «defaultVal(f.type)»; return this.«f.simpleName»; «ELSE» res = this.«f.simpleName»; this.«f.simpleName» = null; return res; «ENDIF» «ENDFOR» default: «fail('''"Key not found: " + key''', x)» } ''' ] overrideIfNotPresent(x, primitiveBoolean, "isEmpty", #[]) [ ''' «FOR f : fields.filter[!type.primitive]» if(«f.simpleName» != null) { return false; } «ENDFOR» return true; ''' ] overrideIfNotPresent(x, primitiveInt, "size", #[]) [ ''' int res = «fields.filter[type.primitive].size»; «FOR f : fields.filter[!type.primitive]» if(«f.simpleName» != null) { res++; } «ENDFOR» return res; ''' ] overrideIfNotPresent(x, primitiveVoid, "clear", #[]) [ ''' «FOR f : fields» «IF f.type.primitive» this.«f.simpleName» = «f.type.defaultVal»; «ELSE» this.«f.simpleName» = null; «ENDIF» «ENDFOR» ''' ] overrideIfNotPresent(x, Set.newTypeReference, "entrySet", #[]) [ ''' «val c = toJavaCode(impl)» return new «c»(this, ALL_KEYS, «c».ENTRY); ''' ] overrideIfNotPresent(x, Set.newTypeReference, "keySet", #[]) [ ''' «val c = toJavaCode(impl)» return new «c»(this, ALL_KEYS, «c».KEY); ''' ] overrideIfNotPresent(x, Collection.newTypeReference, "values", #[]) [ ''' «val c = toJavaCode(impl)» return new «c»(this, ALL_KEYS, «c».VALUE); ''' ] overrideIfNotPresent(x, primitiveVoid, "putAll", #["map" -> Map.newTypeReference]) [ ''' for(Entry<String, ?> e : (Set<Entry<String, ?>>) map.entrySet()) { put(e.getKey(), e.getValue()); } ''' ] } def defaultVal(TypeReference reference) { if(reference.name == "boolean") "false" else "0" } def fail(CompilationContext ctx, String stringExpr, TypeReferenceProvider prov) ''' «val type = prov.newTypeReference(IllegalArgumentException)» throw new «ctx.toJavaCode(type)»(«stringExpr»); ''' def overrideIfNotPresent(MutableClassDeclaration cls, extension TransformationContext x, TypeReference retType, String name, List<Pair<String, Type>> params, CompilationStrategy code) { if (!cls.declaredMethods.exists[simpleName == name && parameters.size == params.size]) cls.addMethod(name) [ addAnnotation(Override.newAnnotationReference) for (p : params) addParameter(p.key, p.value) returnType = retType body = code ] } }
See this example for its effect:
@MapLike(customSet=CustomSet) class TestMapLike { var String name = "self" var int age = 25 var boolean male = true var double knownPiValue = 3.1415926 var List<String> thingsInPocket = #["string", "ring"] } class Program { def static void main(String[] args) { val test = new TestMapLike println("ALL_KEYS") println(Arrays.deepToString(TestMapLike.ALL_KEYS)) println("new HashMap(it)") println(new HashMap(test)) test.put("name", "xtendasy") println("false == " + test.containsKey("nonExistent")) println("true == " + test.containsKey("name")) println("true == " + test.containsValue("xtendasy")) try { test.put("nonExistent", null) throw new AssertionError("Should not get here...") } catch (IllegalArgumentException e) { println("OK! Error: " + e.message) } try { test.remove("nonExistent") throw new AssertionError("Should not get here...") } catch (IllegalArgumentException e) { println("OK! Error: " + e.message) } try { test.put("age", null) throw new AssertionError("Should not get here...") } catch (NullPointerException e) { println("OK! Error: " + e.message) } try { test.put("age", "wrong type!") throw new AssertionError("Should not get here...") } catch (ClassCastException e) { println("OK! Error: " + e.message) } println("keySet") test.keySet.forEach[println(''' «it»''')] println("values") test.values.forEach[println(''' «it»''')] println("entrySet") test.entrySet.forEach[println(''' «it»''')] println("isEmpty " + test.isEmpty) println("size " + test.size) test.clear println("size after clear " + test.size) println("entrySet after clear") test.entrySet.forEach[println(''' «it»''')] } }
Output:
ALL_KEYS [name, age, male, knownPiValue, thingsInPocket] new HashMap(it) {name=self, knownPiValue=3.1415926, age=25, male=true, thingsInPocket=[string, ring]} false == false true == true true == true OK! Error: Key not found: nonExistent OK! Error: Key not found: nonExistent OK! Error: null OK! Error: java.lang.String cannot be cast to java.lang.Integer keySet name age male knownPiValue thingsInPocket values xtendasy 25 true 3.1415926 [string, ring] entrySet name=xtendasy age=25 male=true knownPiValue=3.1415926 thingsInPocket=[string, ring] isEmpty false size 5 size after clear 3 entrySet after clear age=0 male=false knownPiValue=0.0
You may notice that clearing doesn't cause isEmpty to return true. We treat primitives respectfully by resetting them but handling 0 and false as valid values.
If you want nullable behaviour, just use wrapper types like Integer and Boolean and you're done.
That concludes this 3 part series on the MapLike active annotation!
Map interface implementation for your classes (part 2)
Let's start with an implementation for keySet, values, and entrySet.
Implementing Iterator is a basic task. Checking if an entry exists and returning that entry are two similar tasks. It works by iterating all possible keys and checking for existence.
When found (item != null), we could return all three kinds of results: the key that was present, its correspoding value, or an entry with both (that's why we don't care for the generic type and used Iterator<Object>. Let's jump into it (ignore the location of the constants for a second). @Data generates the constructor for us (and other goodies we may need when debugging).
@Data class CustomIterator implements Iterator<Object> { val Map<?, ?> map val List<?> allKeys val int mode var transient current = 0 def loop(boolean change) { var i = current while (i < allKeys.size) { val key = allKeys.get(i) val item = map.get(key) i++ if (item != null) { if (change) { current = i return result(key, item) } return item } } } def result(Object key, Object value) { switch (mode) { case CustomSet.KEY: return key case CustomSet.VALUE: return value case CustomSet.ENTRY: return new SimpleImmutableEntry(key, value) } } override hasNext() { loop(false) != null } override next() { loop(true) } }
We need to wrap that Iterator into a Set. Here we store the constants used earlier.
Subclassing AbstractSet takes all the burden from you. Just provide size and iterator and you're fine. The JavaDoc says what we want to achieve with this class.
/** * Views a {@link Map} as {@link Set}s or {@link Collection}s. * Can be used to implement {@link Map#entrySet}, {@link Map#values}, {@link Map#keySet}. * <pre> * mode {@link CustomSet#ENTRY}: {@link Set} of {@link Entry} objects * mode {@link CustomSet#VALUE}: {@link Collection} of values * mode {@link CustomSet#KEY}: {@link Set} of keys * </pre> * Items are "contained" if they are not {@code null}. * @see CustomIterator */ @Data class CustomSet extends AbstractSet<Object> { public static val KEY = 0 public static val VALUE = 1 public static val ENTRY = 2 val Map<?, ?> map val List<?> allKeys val int mode override size() { map.size } override iterator() { new CustomIterator(map, allKeys, mode) } }
We will glue our solution together in the next post!
Explore search interest for polymer, angular, vaadin, bootstrap, ember by time, location and popularity on Google Trends
Which UI frameworks are popular now and were popular in the past?
Of course there are some missing, Google Trends supports only 5 items.
Explore search interest for jenkins, maven, continuous, dsl, scala by time, location and popularity on Google Trends
What are popular topics in the software world?
How has this changed in past years?
Have you noticed the christmas holidays drops? :)
An interesting slide show for OO programmers
Map interface implementation for your classes (part 1)
Did you ever feel the need to iterate over properties/fields of your classes?
If so, you probably used reflection.
What if you could access your objects like maps?
Just implement the java.util.Map interface and you’re done. But implementing it manually is a boring task. So, let’s automate that using Xtend’s Active Annotations!
Let’s take an example of a Data class: @Data class Point { val int x; val int y }
The Map representation of val point = new Point(2, 4) would be [x=2, y=4].
If Point implemented Map, you could write:
point.get("x"), point.put("y", 42), point.keySet
Start with: @MapLike class Point { val int x; val int y }
In another Xtend project define: @Active(MapLikeProc) annotation MapLike { }
Now comes the work:
class MapLikeProc extends AbstractClassProcessor { override doTransform(MutableClassDeclaration c, extension TransformationContext x) { // Task 1: Let it implement java.util.Map<String, Object> // Task 2: Add all Map methods } }
I will do this step by step:
// Task 1: Let it implement java.util.Map<String, Object> val mapType = Map.newTypeReference(string, object) c.implementedInterfaces = c.implementedInterfaces + #[mapType]
The next step is implementing the methods. And there are plenty:
interface Map { V get(Object key); V put(T key, V value); boolean containsKey(Object key); boolean containsValue(Object key); V remove(Object key); boolean isEmpty(); int size(); void putAll(Map<? extends K, ? extends V> m); void clear(); Set<K> keySet(); Collection<V> values(); Set<Map.Entry<K, V>> entrySet(); }
The easiest way to do this is using a helper function overrideIfNotPresent:
def overrideIfNotPresent(MutableClassDeclaration cls, extension TransformationContext x, TypeReference retType, String name, List> params, CompilationStrategy code) { if (!cls.declaredMethods.exists[simpleName == name && parameters.size == params.size]) cls.addMethod(name) [ addAnnotation(Override.newAnnotationReference) for (p : params) addParameter(p.key, p.value) returnType = retType body = code ] }
Now we can implement these methods! Start with a dummy implementation to make your code compile.
// Task 2: Add all Map methods cls.overrideIfNotPresent(x, object, "get", #["key" -> object]) [ ''' return null; ''' ] cls.overrideIfNotPresent(x, object, "put", #["key" -> string, "value" -> object]) [ ''' return null; ''' ] cls.overrideIfNotPresent(x, primitiveBoolean, "containsKey", #["key" -> object]) [ ''' return false; ''' ] cls.overrideIfNotPresent(x, primitiveBoolean, "containsValue", #["obj" -> object]) [ ''' return false; ''' ] cls.overrideIfNotPresent(x, object, "remove", #["key" -> object]) [ ''' return null; ''' ] cls.overrideIfNotPresent(x, Set.newTypeReference, "entrySet", #[]) [ ''' return null; ''' ] cls.overrideIfNotPresent(x, Set.newTypeReference, "keySet", #[]) [ ''' return null; ''' ] cls.overrideIfNotPresent(x, Collection.newTypeReference, "values", #[]) [ ''' return null; ''' ] cls.overrideIfNotPresent(x, primitiveBoolean, "isEmpty", #[]) [ ''' return true; ''' ] cls.overrideIfNotPresent(x, primitiveInt, "size", #[]) [ ''' return 0; ''' ] cls.overrideIfNotPresent(x, primitiveVoid, "putAll", #["key" -> Map.newTypeReference]) [ ''' return; ''' ] cls.overrideIfNotPresent(x, primitiveVoid, "clear", #[]) [ ''' return; ''' ]
Implementing these methods correctly is not that easy. So, stay tuned for more!
Heute eine Session beim Bar Camp Kiel 2016. Um 16.00 im networkteam Raum.
Do it yourself programming language features
As shown in the last post you can extend Xtend by using active Annotations. Here are some features you might want to have in your programming language, but it is currently not available. I'll show you how to implement these in Xtend.
Partly dynamic programming using the Map interface
F#'s type providers to access remote data sources while exploring them in your IDE
F#'s descriminated unions / Scala's case classes / Haskell's sum types
Stay tuned!
Xtend Active Annotations
Xtend's Active Annotations like @Data take the burden from you to write boilerplate code. With @Delegate you can simulate Mixin inheritance, a feature some programming languages praise as super cool:
import org.eclipse.xtend.lib.annotations.Delegate interface Wizard { def int castSpell() } interface Warrior { def int hitWithSword() } class ApprenticeWizard implements Wizard { override castSpell() { 42 } } class ApprenticeWarrior implements Warrior { override hitWithSword() { 1337 } } class SwordMage implements Wizard, Warrior { @Delegate Wizard wizard = new ApprenticeWizard @Delegate Warrior warrior = new ApprenticeWarrior } class MixinProgram { def static void main(String[] args) { val character = new SwordMage() println(character.hitWithSword) println(character.castSpell) } }
So, to sum up, Xtend's features are programmable by you and me!
Here's an overview of what developers made:
blog.efftinge.de
@FXBean for easy JavaFX programming
xtend-contrib
@Builder for the Builder pattern
@Messages a typesafe wrapper for xy.properties locales
@Cached for memoization of pure methods
@Log for logging, various libs are supported
plugback
@Hook for interceptors
xtension
@Getter / @Setter for properties with optional laziness
@Mix for mixin inheritance
Powershell - profile and functions
The best way to use it is via the dev env Powershell ISE which is shipped with v4.0: KB2819745.
To create reusable commands, you first should create a profile by putting a directory WindowsPowershell inside your home documents folder, so it looks like this: C:\Users\(your user name)\Documents\WindowsPowerShell
Place a file called profile.ps1 in this directory and put "Hello $env:userName!" in it. The next time you start Powershell, you will be greeted. This shows that this code is executed on startup.
This is the best place to load your own commands, so you can use them each session. You can do it by putting this also into your profile:
get-childitem "$env:userProfile\Documents\WindowsPowerShell" | where-object { $_.fullName.endsWith(".ps1") } | where-object { -not $_.fullName.contains("profile") } | foreach-object { invoke-expression $_.fullName "$_ loaded!" }
What happens here is this:
get-childitem "$env:userProfile\Documents\WindowsPowerShell" returns all files in your powershell profile.
| passes these files to the next processing step
$_ denotes the current object that is processed
where-object { $_.fullName.endsWith(".ps1") } filters all files that end with .ps1
where-object { -not $_.fullName.contains("profile") } filters out your profile (otherwise you'll get an infinte loop)
foreach-object { ... } does something with the filtered files
invoke-expression $_ interprets / executes the file
"$_ loaded!" writes what file was loaded to the screen
To define a reusable function you should structure it like this, with meaningful documentation. For example, place a file print-time.ps1 with this content in your powershell profile folder:
<# .Synopsis Prints the current date and time to the screen. #> function global:print-time { write-host (get-date) }
You can later read these docs which tell you how to use your functions. If you start up powershell you're good to go!
Windows PowerShell Copyright (C) 2013 Microsoft Corporation. Alle Rechte vorbehalten. Hello xtendasy.blogger! print-time.ps1 loaded! PS C:\Users\xtendasy.blogger> get-help print-time NAME print-time ÜBERSICHT Prints the current date and time to the screen. SYNTAX print-time [] BESCHREIBUNG VERWANDTE LINKS HINWEISE Zum Aufrufen der Beispiele geben Sie Folgendes ein: "get-help print-time -examples". Weitere Informationen erhalten Sie mit folgendem Befehl: "get-help print-time -detailed". Technische Informationen erhalten Sie mit folgendem Befehl: "get-help print-time -full". PS C:\Users\xtendasy.blogger> print-time 17.06.2016 17:02:22 PS C:\Users\xtendasy.blogger> _
This is the output on a german computer.
Powershell - automating day-to-day tasks
For Windows users there is a great tool called Powershell that enhances the cmd.exe greatly.
It's installed on Windows 7 and later, so just launch it: Press [Win]+[R], type powershell, and press [Enter].
It behaves like the old command line but comes with objects. So, if you execute dir you get an array of FileInfo .NET objects.
There's an Powershell dev environment shipped with v4.0: KB2819745
So if you find yourself copying and/or extracting files every day, go automate it as a reusable function.