Intellij structural replace change method signature - intellij-idea

I'd like to change a method with a certain signature:
public OldReturnType get.*(Params) {
//lots of code
}
to this:
public NewReturnTyp get.*(Params) {
//lots of code
}
-> I'd like to replace the return type. I tried this with SSR:
Copy existing Template "methods of the class". This yields the template:
class $Class$ {
$ReturnType$ $MethodName$($ParameterType$ $Parameter$);
}
I first tried to replace $ReturnType$ OldType and NewType respectivly:
Search Template:
class $Class$ {
OldType $MethodName$($ParameterType$ $Parameter$);
}
Replace Template:
class $Class$ {
NewType $MethodName$($ParameterType$ $Parameter$);
}
This gives me all the methods, but if I replace it, the method gets removed.
I then tried to changed the pattern the following way:
Search Template:
class $Class$ {
$OldType$ $MethodName$($ParameterType$ $Parameter$);
}
And specified, that $OldType$ should be the target of the search. I also specified a RegEx pattern: OldType for this variable.
Replace Template:
class $Class$ {
NewType $MethodName$($ParameterType$ $Parameter$);
}
This also finds all the methods but they get removed if I replace. I tried very different, always with the same result: The method gets removed if I replace the match. How do I have to specify the search/replace Template to just replace OldType with NewType in the signature.

You have encountered a bug in Structural Search & Replace. Probably this one: https://youtrack.jetbrains.com/issue/IDEA-127835
But there is a workaround. Use the following Search Template:
class $Class$ {
OldType $MethodName$($ParameterType$ $Parameter$) {
$statement$;
}
$other$;
}
Make sure "This variable is target of the search" for $MethodName$ is NOT set, or it won't work.
$statement$
minimum count: 0
maximum count: unlimited
$other$
minimum count: 0
maximum count: unlimited
The rest as in the methods of the class existing template.
Replacement Template as you would expect is the same as the Search Template, only with NewType replacing OldType.
Let me know if it works, or if you have any more problems.

Related

Invoke receiver function declared in interface

I'm trying to create an easy-to-use html generator for a personal project. I thought I would use extension functions to be able to generate an html programmatically using something like this:
html {
head {
title("Site title")
}
body {
div {
// stuff in div
}
}
}
For that I declared an interface:
fun interface TagBlock {
operator fun Tag.invoke()
}
Where Tag would be the class designating the specific tags, like html, body, div etc:
class Tag(val name: String)
I now tried to create a function which accepts the earlier mentioned interface and returns a tag:
fun html(block: TagBlock): Tag {
val html = Tag("html")
// invoke `block` with `html`
return html
}
I'm stuck on how to invoke the provided parameter block. The following all don't work:
block(html) // Unresolved reference
block.invoke(html) // unresolved reference
html.block() // Unresolved reference: block
Where am I doing something wrong?
The invoke() operator you're declaring has 2 receivers:
the dispatch receiver TagBlock
the explicit receiver Tag
You need to provide the dispatch receiver in the context of your call for it to work. You can do this with the library function with():
fun html(block: TagBlock): Tag {
val html = Tag("html")
with(block) {
html.invoke()
}
return html
}
This may or may not be the usage experience you were looking for, though.
A more idiomatic approach in Kotlin would be to just take a function type as input:
fun html(block: Tag.() -> Unit): Tag {
val html = Tag("html")
html.block()
return html
}

Vue.js: using a data object's method in inline event handler

I have a Vue(2.5+) component where I'm setting a data property to a new Foo object. Using foo.bar() in the click handler calls the method correctly, but throws Uncaught TypeError: cannot set property 'someVariable' of null when trying to modify properties inside the Foo class. Setting it up so that Foo is an object literal instead of a class also does not resolve the error.
I suspect something weird is happening with this, between the component and the class?
Vue component
import Foo from './foo.js'
export default {
template: `<div #click="foo.bar"></div>`,
data() {
return {
foo: new Foo()
}
},
created() {
console.log(foo); // foo is not null here
}
}
Foo class
export default class Foo
{
constructor()
{
this.someVariable = 0;
}
bar(e)
{
// modify this.someVariable
}
}
but if I change the vue component to reference the external method through it's own "methods" property, it works.
Vue component (working)
import Foo from './foo.js'
export default {
template: `<div #click="bar"></div>`,
data() {
return {
foo: new Foo()
}
},
methods: {
bar(e) {
this.foo.bar(e);
}
}
}
As said in the comments, foo.bar without any context attached to it :
In JS functions are objects, just like any object they have their own this "pointer".
In the evaluation of their body, this is bound to a specific object referred to as context which is either the default context (automatically set) or user defined (manually set).
Inheritance in JS is achieved through a prototype chain and methods should be defined on/attached to the class's prototype. Because of this, when you call foo.bar() :
You are in a method call context, therefore foo will be bound to the method
bar is searched on the object first then in the prototype chain
But methods behave just like any other property : when you do foo.bar you get a reference to the actual method which is an unbound function (default behavior for methods, since it is bound when called on an object).
Therefore, what you really need to do in this situation is foo.bar.bind(foo).
I would also suggest taking a quick look into this ES6 proposal for a bind operator and its implementation as a Babel plugin which allows nice things like passing ::foo.bar instead of foo.bar.bind(foo)

Is it possible to overwrite the behavior of materialize css navbar and make it into a bootstrap style?

I was thinking to use bootstrap and materialize css but it happen that they have the same class.
If you want to add custom style to an object that already has it's style defined by other css class, sometimes you will have to replace some styles. Here's how to do it:
Firstly, check which class overrides it.
Let's say your markup returns:
<div class="range-specific range"></div>
If your css is defined like that:
.range-specific { foo; }
.range { bar; }
Then the range will win.
If you change it to:
.range-specific.range { foo; }
.range { bar; } `
Then the specific will win.
If you want to hack it even more, do this:
.range-specific.range-specific { foo; }
.range { bar; }
And specific will surely win.
It's even better to do this:
.range { bar; }
.range-specific { foo; }
If u want to override that class you can use nav.app-bg or use !important
Here you can check Overrides of Material-UI

Unable to access VM properties from #inlineView

I've created a simple custom element in Aurelia that uses an #inlineView() (because the view is tiny) but when I try to access one of my VM's properties from my inline view I just get "property is not defined";
import {inlineView} from 'aurelia-framework';
#inlineView(`<template><h1>${title}</h1></template>`)
export class MyCustomElement {
constructor () {
this.title = 'Hello, World!';
}
}
This happens with #bindable as well;
export class MyCustomElement {
#bindable title = 'Hello, World!';
constructor () {
}
}
When the <template><h1>${title}</h1></template> is being interpreted, the interpreter tries to interpolate the title variable which does not exist yet. Try this:
#inlineView(`<template><h1 innerHTML.bind="title"></h1></template>`)
Or even easier:
#inlineView('<template><h1>${title}</h1></template>') // without accents
The problem is you are using a template literal in your inlineView decorator which is causing Javascript to evaluate ${title} before it gets passed to the inlineView decorator function. At that point, title does not exist. You need to pass a regular string in this instance using regular quotes (' or ") around the template string like so:
#inlineView("<template><h1>${title}</h1></template>")

Why is it possible to export variable of private type

Think like this :
package first
type person struct {
Name string
}
var Per = person{
Name: "Jack",
}
and in main package
package main
import "first"
import "fmt"
func main(){
o := first.Per
fmt.Println(o)
}
the above works, as we can see that the variable in first package was visible outside but it's type was not, but it gives no error? And how it can be useful outside package?
it is fine:
Exported identifiers:
An identifier may be exported to permit access to it from another
package. An identifier is exported if both:
the first character of the identifier's name is a Unicode upper case
letter (Unicode class "Lu"); and
the identifier is declared in the
package block or it is a field name or method name. All other
identifiers are not exported.
ref: https://golang.org/ref/spec
and even you can use Getters:
Go doesn't provide automatic support for getters and setters. There's
nothing wrong with providing getters and setters yourself, and it's
often appropriate to do so, but it's neither idiomatic nor necessary
to put Get into the getter's name. If you have a field called owner
(lower case, unexported), the getter method should be called Owner
(upper case, exported), not GetOwner. The use of upper-case names for
export provides the hook to discriminate the field from the method. A
setter function, if needed, will likely be called SetOwner. Both names
read well in practice:
owner := obj.Owner()
if owner != user {
obj.SetOwner(user)
}
ref: https://golang.org/doc/effective_go.html
so if you do not want to export Name make it lower case, like this working sample codes and use Getter/Setter :
package first
type person struct {
name string
}
var Per = person{
name: "Jack",
}
func (p *person) SetName(name string) {
p.name = name
}
func (p *person) Name() string {
return p.name
}
main.go (with commented output):
package main
import "first"
import "fmt"
func main() {
person := first.Per
fmt.Println(person.Name()) //Jack
person.SetName("Alex")
fmt.Println(person.Name()) //Alex
}
another use cases:
Singleton pattern
Essentially, it's a singleton pattern. The package exports a single instance of person but because the type is private you can't create another instance out of it.
Better implementation would be to export a function that returns a singleton instance of a private type. On first invocation it will create the instance in a thread-safe manner.
var (
p *person
once sync.Once
)
type person struct {
Name string
}
func Per() *person {
once.Do(func() {
p = &person{
Name: "Jack",
}
})
return p
}
sync.Once allows you to execute a piece of code only once even if multiple goroutines are trying to execute it.