I have a variable like this:
People model=Mock()//created by spock' mock
How to change the variable name "model" to "model_0" by reflection?
I doubt there is any way to do that with reflection. I'm with #tim_yates in this one.
I'm no bytecode/compiler expert, but i do believe variable's names turn into symbols upon compilation, so they are not changeable at all. The following Java class:
public class Var {
void a() {
int myVar = 1;
myVar += 1;
}
}
Upon compilation and decompilation (using jd-gui), the code turns into:
public class Var
{
void a()
{
int i = 1;
i++;
}
}
The variable name changed.
On Groovy, you can go for ASTs, which will give you full power over the generated tree. The following class:
class Asts {
def wat() {
Integer myVar = 90
}
}
Will generate the following AST:
Now you can write your own AST transformation to make the changes. Doesn't seem worth to me, though, a collection or map should suffice.
Related
I have this ts.Program/ts.SourceFile:
class MyClass {
foo() {
// #1
}
}
Is there a way to obtain the symbol/type of the local this value at position #1?
Unfortunately, this is not listed by checker.getSymbolsInScope.
Ideally I would get the type of MyClass, so I could explore its members.
The solution should also work for these cases:
function foo(this: MyClass) {
// #2
}
const obj = {
bar() {
// #3
}
};
Thank you!
edit: This is the feature I needed this for:
There is an internal TypeChecker#tryGetThisTypeAt(nodeIn: ts.Node, includeGlobalThis = true): ts.Type method that will return this information. If you're ok with using internal API, then you can do:
const type = (checker as any).tryGetThisTypeAt(nodeName) as ts.Type;
To get the node's name, you'll need to traverse the tree to find the method or function declaration that is contained within the position, then the .name property will contain the node that you can provide to tryGetThisTypeAt.
I want to merge class declarations in a .dt.s file to generate a cleaner public API. I am stuck on how to make this work with generic type arguments. Let's say I have:
class A1<T> { // Non-exported class I want to hide
data?: T;
}
export class B1 extends A1<string> {
}
Ideally, I want to turn this into:
export class B1 {
data?: string;
}
I can get the type of A1 and then copy its members. But how do get a resolved version of A1 that uses string instead of T?
For reference, this is my current code:
for (const heritageClause of node.heritageClauses) {
for (const type of heritageClause.types) {
if (isExported(type.modifiers)) {
exportedTypes.push(type);
} else {
const privateType = typeChecker.getTypeAtLocation(type);
if (privateType?.symbol?.members) {
privateType.symbol.members.forEach((definition, memberName) => {
if (!currentMembers || !currentMembers.has(memberName)) {
additionalMembers.push(...definition.declarations);
}
}
});
}
}
}
I believe the method you are looking for is TypeChecker#getTypeOfSymbolAtLocation(symbol, node).
The following should get the resolved type of string | undefined:
// by the way, recommend renaming `type` to `typeNode` to avoid confusion
typeChecker.getTypeOfSymbolAtLocation(privateType.getProperties()[0], type);
I have a bunch of variables in a class. There are situations when I want to set then to null/ "temp" etc as per a well defined logic. The challenge is to list out the variables at multiple places- tedious and error-prone.
classname.speed=NaN
classname.speedtype="not_set"
classname.distance=NaN
classname.distancetype="not_set"
Ideally, would prefer a way to refer to these variables programatically and set something like
"for all class variables- if variable ends in type, set as "not_set"; for other variables set as NaN
How can I achieve this? Any pointers will help
The simplest approach would be just write function to clear them all.
If you want something more automatic, it will requre efforts - look at introspection api. Basically, you call describeType on your class and it returns XML description. All variables will be listed there, along with other info. Then you can parse returned XML and set all variables to needed value, accessing them dynamically with square bracket syntax:
var myClass:MyClass = new MyClass();
myClass["varName"] = "new value";
It can be achieved through Inheritance i.e. implementing interface or extending class
which contains common fields
public class MyClass
{
public a:String = null;
public b:String = null;
public function MyClass()
{
}
}
which contains common var and Child Class could be
public class MyClassChild extends MyClass
{
public var c:String = null;
public function MyClassChild()
{
super();
this.a ="";
this.b ="";
}
}
and you can cast or use for each loop to set values
var temp:MyClassChild = new MyClassChild ();
MyClass(temp).a = "Hello World";
Hopes that helps
please help me out , why my code cannot compile,
the compiler complains that:
error C2629: 意外的“StringToAnsi (”
error C2334: “{”的前面有意外标记;跳过明显的函数体
error C2629: 意外的“StringToAnsi (”
...
Here is my code:
#using <System.dll>
#using <mscorlib.dll>
class StringToAnsi
{
private:
void * m_ptr;
public:
StringToAnsi( System::Object ^ str)
{
m_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(safe_cast<System::String^>(str)).ToPointer();
}
StringToAnsi(System::String ^ str)
{
m_ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str).ToPointer();
}
~StringToAnsi()
{
System::Runtime::InteropServices::Marshal::FreeHGlobal(System::IntPtr(m_ptr));
}
operator const ACHAR*()
{
return (const ACHAR*)m_ptr;
}
Because you have two constructors with the same number of parameters. There is an Object and a String, but both are an Object. So this seems very ambiguous.
When you create two methods (or constructors), you can't let them have the same number of parameters, because the compiler doesn't know which one to call.
When you put in a string into the construction like so: new StringToAnsi("bla"). The compiler doesn't know which constructor to use.
Say I have four sub-classes of 'Car'. One for each color. I want to have one function that can build and return a 'color-car' sub-class based on the passed value. This is a dumb example, I know, but it is precisely what I am trying to do only on a smaller scale.
public class Car
{
}
public class BlueCar extends Car
{
}
You get it.
Then, in another (helper) class, I have a function which takes in a string of the color and returns the correct sub-class.
public function GetCarFromColor(_color:String):Car
{
if (_color == "blue")
{
var myCar:BlueCar = new BlueCar;
return myCar;
} else if (_color == "red")
{
var myCar:RedCar = new RedCar;
return myCar;
}
Ok. You get it. This doesn't work for a reason unknown to me. I get 1118 errors which complain about conversion of BlueCar into Car, etc...
Can someone help me out here? Thanks!
Make the return variable to be of the supertype:
public function GetCarFromColor(_color:String):Car
{
var myCar:Car
if (_color == "blue")
{
myCar = new BlueCar;
return myCar;
} else if (_color == "red")
{
myCar = new RedCar;
return myCar;
}
This should now compile ok.
You should try casting your derived class to the base class before returning it back.
Not sure about actionscript but in C++ you could do it like this
Base *GetCarFromColor()
{
Base *b1;
b1 = new D1;
return b1;
}
Maybe you should use an interface instead?
public interface ICar
{
}
public class BlueCar implements ICar
{
}
public function GetCarFromColor(_color:String):ICar
{
}
The reason you were getting errors is because you have two local variables of the same name with different types in one function:
var myCar:BlueCar = new BlueCar;
var myCar:RedCar = new RedCar;
The variable myCar is typed as both BlueCar and RedCar. In ActionScript 3, variables are always scoped to the entire function. In other languages, like Java, I know that if statements and loops create a new block-level scope, but that's not the case here.
As Matt Allen suggested, typing myCar as the superclass, Car, should stop these compiler errors.