We had explicitly disabled R8 using directive
android.enableR8=false.
But when I take that directive out of my gradle.properties I am finding that R8 is removing lot of application specific classes.
Only way I am able to compile and run the app successfully is by including following statement in my config/proguard/proguard-project.txt
-keep class com.myapppackage.** { *; }
My gradle.properties looks like this:
kotlin.incremental.usePreciseJavaTracking=true
android.useAndroidX=true
android.enableJetifier=true
android.uniquePackageNames=true
In google's document ( https://developer.android.com/studio/build/shrink-code ) there is no mention that I need to explicitly have keep directive.
Whenever you use a shrinker (R8 or ProGuard) it will use the provided keep rules to determine the possible entry points into the program. These entry points include any reflection used in the app. Android Studio has a set default keep rules (generated by getDefaultProguardFile('proguard-android-optimize.txt')) which, together with the rules generated by aapt2, will work for many apps. However if an app uses reflection beyond what these rules cover additional rules will be required. The conservative rule that you are using (keeping everything in the app pacakge and sub-packages) sould work for most apps, but you will end up keeping more than required.
You can add -printconfiguration <some file> to your proguard-rules.pro to see all the rules which are actually passed to R8.
Related
I'm using Kohana framework which allows for multiple class definitions (in application and system subfolders). I'm using phpstorm as an IDE which gives me messages multiple definitions exist for class . Is there any way to tell phpStorm which class definition is correct?
Is there any way to tell PhpStorm which class definition is correct?
You cannot, unfortunately.
https://youtrack.jetbrains.com/issue/WI-17646 -- watch this ticket (star/vote/comment) to get notified on any progress.
ATM you either just ignore the under-waving .. or you can configure that inspection to not to report such cases (Settings/Preferences | Editor | Inspections | PHP | Undefined | Undefined class, it has Don't report multiple class declaration potential problems checkbox).
Even with that inspection configured, IDE will still ask you what class declaration to jump to (and this is correct behaviour as IDE does not know if you want to see the original implementation or implement your own).
The only other way is to ensure that there is only one class with the same name in the project. For that you may use:
Mark whole folder as excluded
Mark individual file as Plain Text
Both are available via content menu in Project View and applicable to project files only (e.g. will be unavailable or will do nothing useful if tried to apply in Library scope).
You should just ignore the complete cache folder.
Go to Settings > Directories
Choose var\cache
Set it to 'Excluded'
From: https://github.com/Haehnchen/idea-php-symfony2-plugin/issues/301
I've found a possible solution to my problem - I can mark file as plain
As variant you can turn off inspection only for specific class. Put cursor inside underwaved class name, then Alt+Enter → Inspection options → Supress for statement
PHPStorm adds
/** #noinspection PhpUndefinedClassInspection */
above class declaration and class name is not underwaved anymore.
I've been around the web everywhere and not a single option worked for me... I've been struggling for months with it, and today I found a solution, so if none of the above works for you, try redefining the PHP Include Path List. under Settings > Languages & Frameworks > PHP, make sure only the folders containing paths to source used by your project or application is configured.
My scenario is that I do a lot of package development, and while my packages are all in one project, they are also "symlinked" in "vendor" in my composer configuration, so there is duplicated code found by PHPStorm, in the vendor folder and my packages folder. Similarly, if include paths are duplicated, or paths are configured to find code outside of your project, which is already part of the project, it will also find multiple definitions. So, excluding the symlinked folders in vendor, allows PHPStorm to only find one copy of the source to my packages, and if my packages contain vendor folders of their own, they will also show up as duplicated definitions. Remove anything in the Include Path list where it may find dipplication
Just some addition to the Andy White's comment:
Settings | Editor | Inspections | PHP | Undefined | Undefined class | Don't report multiple class declaration potential problems
I really couldn't find this config and thought it was no there now, but this is still there, but very well hidden)
It is a little counterintuitive and inconspicuous, but the needed checkbox is in the right panel, and appears only if you click on the Undefined class row:
Prolog
Guess there are several ways to solve this problem. Actually, it's just a warning and it says that phpstorm can't provide you with autocompletion so you have to work a bit harder :D
I had the same problem as many others here and solved it by ignoring unwanted.
Scenario
Had a git project with a vendor-folder after composer install. Also, there is a my-project.phar in this project that also contains some vendor stuff and this caused my warnings.
Solution
File > Preferences|Settings > Directories
There you have to possibility to exclude files and folders. In my case it's the .phar so it's a "file" and you can add it at the bottom of the settings-window.
PHPStorm will no longer see duplicates.
This is very project-specific and I guess most people have to find their own solution but pointing to this may help to find the problem easier.
Hope this helps someone :)
Somewhere in your project there are multiple definitions for the same class. I discovered I had backup copies in my project which caused this warning. I removed the backups from my Project (a good idea anyway) and it fixed the error.
I don't know how you created the other definition, but if you or anyone has this issue due to calling class_alias(), then you can solve this issue quickly.
Consider
class_alias(
'The\AliasClass',
'My\RealClass',
true
);
and
class_alias(
'The\AliasClass',
'My\Real'.'Class', // <-- break up the string
true
);
With the latter, PhpStorm will not pick up the My\RealClass and your "multiple definition" warning will cease. This is an ancient JavaScript trick to embed HTML in a string literal, by the way.
This warning has annoyed me for a long time. I believe the answers here saying there is a duplicate file somewhere is correct. The reason I am getting the warnings are due to the autocomplete file to give phpStorm a hint on how to find codeIgniter functions. If you are doing this also that is the reason for some of the warnings. The autocomplete file makes phpStorm think there are two different definitions. However, I like autocomplete more than I dislike the warnings so I guess I have to live with them.
This is the autocomplete I'm referring to:
IntelliJ IDEA 12 not finding CodeIgniter classes, throwing errors
Alternatives that work after a fashion, but aren't so good
marking the file B you don't want to be used by autocomplete as "plain" or excluded, leaving file A active: this will disable notifications in the file C, but will also make autocompletion no longer work for whatever is in file B. So if somewhere else you use something that's rightly in B, and maybe there you want to exclude A from autocompletion, you can't do that.
disable the inspection: this will also disable undefined class warnings, so if I make any typos in any class name, I'll only discover this after deployment (or from the fact that autocomplete stops working for that object).
"Don't report multiple class declaration potential problems" - this is very nearly good, but I don't like having "potential problems" ignored; what if I create a class with an unwittingly duplicated name that is in use somewhere else? Granted that I'll catch it (or phpunit will), but still.
The best I've found so far
The way to go for now, at least until a more focused configuration is available for PHPStorm (e.g. "Alternative Classes"), is to mark those notifications - and only those - as ignorable:
/* #noinspection PhpUndefinedClassInspection */
/**
* Verify an existing contract. Requires agent and supervisor.
*
* #param array $data
* #param Cliente $cli
* #param User $age
* #param User $sup
* #return Contratto
*/
private function contratto(
array $data,
/* #noinspection PhpUndefinedClassInspection */
Cliente $cli,
/* #noinspection PhpUndefinedClassInspection */
User $age,
/* #noinspection PhpUndefinedClassInspection */
User $sup
) {
Note that to disable notifications in the PHPDoc comment I had to add a directive before the comment; this did not disable the notifications for the three parameters.
In the future, I wish to be able to specify those in PHPStorm as
* #param array $data raw data for the contract
* #param \local\foobar\Cliente $cli customer opening the contract
private function contratto(
array $data,
/*\local\foobar\*/Cliente $cli,
or better still, explicitly use a new PHPdoc tag such as "#replaces". So PHPStorm would know that my class is the one not replaced. I'll also have to decorate my use's to specify the class I'll be actually using.
And run a search for "#noinspection PhpUndefinedClassInspection" throughout my code.
Another way
The above problems stem from the fact that I have a "master" Customer class which is overridden by a "local" modification for the foobar client, whose Customers have (say) a special method.
The "correct" way of doing this should be to declare a FoobarCustomer which is only employed by foobar's code, and is a child class of Customer. Of course this is only possible if the child class is in my code, not in the framework's, and also I may need some methods in the parent class to be protected rather than private, which may make this solution either impossible or needful of Reflection:
/**
* Verify an existing contract. Requires agent and supervisor.
*
* #param array $data
* #param FoobarCliente $cli
* #param FoobarUser $age
* #param FoobarUser $sup
* #return Contratto
*/
private function contratto(array $data, FoobarCliente $cli, FoobarUser $age...
I had similar problem and it was quite annoying one. I was using Yii2 framework and as it turned out at the end I have accidentally created en extra "vendor" folder and composer.json in the root of the project (not in the root of the app) so I ended up with that warning as phpStorm was confused which extension folder is the right one.
I've deleted extra vendor folder and it solved the problem.
Try delete duplicate declared libraries
Settings -> Languages & Frameworks -> PHP -> Include Path
I resolved this in my case by removing a more specific entry in my composer.json that included code by another more general entry
Now I have AppA finished. but I want to make AppB,AppC. and AppB,AppC share most of the code in AppA(including xaml, asset, code,etc.). only a few changes for the AppB,AppC respectively.I mean, the 3 apps can be installed on the same windows phone separately with different icons.
Does anybody know how to build AppB,AppC referring AppA in code?
thanks.
Either extract as much as you can in a shared/common project or use "Add as Link" to include files from AppA into AppB and AppC.
Note that XAML files don't support conditional compilation so they must be identical for all projects in order to link them. You can potentially extract XAML differences into App.xaml StaticResources (identical keys) in order to make them identical and link them.
Sharing XAML is very reasonable when targeting the same platform.
You can also link cs files even if they are similar (few changes) by using conditional compilation.
Partial classes can also spare you the conditional compilation ceremony in many cases.
Finally Resource files are very good candidate for reuse. If you decide to put them on a shared library remember to wrap the generated Resource class in another public one with a public constructor shown here in order to avoid the internal constructor issue.
You can put all your code in an external class library. As far as I know though your assets and pages need to exist in each project.
If you want to share code and assets between multiple assemblies, you can create a class library for Windows Phone and put all the code inside it. When you need to use that library, simply link it in your target applications.
When you want to navigate to a page in your library, use the following syntax:
NavigationService.Navigate(new Uri("/AssemblyName;component/page.xaml", UriKind.Relative));
I'm making a game and I an in-game editor that is able to create entities on the fly (rather than hard coding them). I'm using a component-aggregation model, so my entities are nothing but a list of components.
What would be the best way to obtain or generate a list of components? I really don't want to have to manually add entries for all possible components in some giant registerAllComponents() method or something.
I was thinking maybe somehow with reflection via either the knowledge that all components inherit from the base Component class, or possibly via custom metatags but I haven't been able to find ways to get a list of all classes that derive from a class or all classes that have custom metatags.
What sort of options am I left with?
Thanks.
For a project I did once, we used a ruby script to generate an AS file containing references to all classes in a certain package (ensuring that they were included in the compilation). It's really easy considering that flash only allows classes with the same name as the file it's in, so no parsing of actual code needed.
It would be trivial to also make that add an entry to a dictionary (or something similar), for a factory class to use later.
I believe it's possible to have a program execute before compilation (at least in flashdevelop), so it would not add any manual work.
Edit: I added a basic FlashDevelop project to demonstrate. It requires that you have ruby installed.
http://dl.dropbox.com/u/340238/share/AutoGen.zip
Unfortunately, there is no proper way of getting all loaded classes or anything like that in the Flash API right now. So finding all sub-classes of Component is out, inspecting all classes for a specific meta tag is out as well.
A while ago I did run into a class/function that inspected the SWF's own bytecode upon loading to retrieve all contained classes. That's the only option for this kind of thing. See this link and the bottom of my post.
So, you're left with having to specify a list of component classes to pick from.
One overly complicated/unfeasible option that comes to mind is creating an external tool that searches your source folders, parses AS3 code and determines all sub-classes of Component, finally producing a list in some XML file. But that's not a task for the faint-hearted...
You can probably think of a bunch of manual solutions yourself, but one approach is to keep an accessible Array or Vector.<Class> somewhere, for example:
public static const COMPONENT_LIST:Vector.<Class> = Vector.<Class>( [
CollisionComponent,
VisualComponent,
StatsComponent,
...
...
] );
One advantage over keeping a list of String names, for example, would be that the component classes are guaranteed to be compiled into your SWF.
If the classes aren't explicitly referenced anywhere else in your code, they are not compiled. This might occur for a simple component which you only update() once per frame or so, and is only specified by a string in some XML file.
To clarify: You could use the code in the link above to get a list of the names of all loaded classes, then use getDefinitionByName(className) for each of them, followed by a call to describeType(classObj) to obtain an XML description of each type. Then, parsing that for the type's super-types, you could determine if it extends Component. I personally would just hardcode a list instead; it feels too messy to me to inspect all loaded classes on startup, but it's up to you.
In my project there is some common package which gets its dependencies resolved by the UnityContainer which is defined in unity.config file.
There is another custom package which I want to have its own custom UnityContainer in a seperated CustomUnity.config file.
In runtime I want both files to be loaded and when I get the unity section, I want it to contain both UnityContainers.
How can i achieve it?
Thanks!
The UnityContainer.LoadConfiguration method can be called multiple times on the same container. Each time it loads whatever's in that configuration section, but it doesn't remove what was previously in the container - it's additive. If there's a conflict (both sections configure the same type) then last one in wins.
So, the approach would be to use the ConfigurationManager APIs to load your two separate UnityConfigurationSections, and then call LoadConfiguration twice, once for each configuration section. That should be all you have to do.
I wrote a library that lets you write your ioc container configuration in modules. It supports unity but you will have to configure your container in codes instead of using the files. I don't know if will solve your problem, but you can check it out at bootstrapper.codeplex.com
I need to override a function in this file:
app/code/core/Mage/Core/functions.php
The problem is that this is so core that there’s no class associated to it, probably because Core isn’t even a module. Does anybody know how to override a function in the file without a class?
Any help would be appreciated.
Copying the file to app/code/local/Mage/Core/functions.php should not be used because of the following reasons:
The entire file has to be copied over making it harder for us to identify what changes have been made.
Future upgrades could introduce new features that would not be available unless it is remembered to copy across the new version of that file and implement the changes again.
Future upgrades could address bugs with core that we would miss unless it is remembered to copy across the new version of that file and implement the changes again.
In respect to points 2 & 3 each upgrade could change the way things work that means revisiting what changes we need to make. In some cases this will be true for overriden methods as well but at least we can easily identify where those changes effect us.
What do you do if another person wants to use the same technique? Being able to identify what is core code and what is ours becomes more and more complex.
Keeping our code together as a “module” becomes more difficult as by copying in the core file means that we have effectively locked it into being “guaranteed” to run on the version of the software that we have copied the original code from. It also means reusing this work is a lot more difficult to do.
Identifying why the code was changed it much harder as it is outside our namespacing, ie all development related to “Example_Module” is in the namespace:
/app/code/core/local/Example/Module
whereas code copied to app/code/core/local/Mage only indicates that we have made a change to support an unknown feature etc.
Also Magento occasionally release patches which fixes bugs – these will only patch files inside core leaving your copied file without the patch.
What I would suggest instead is that you write your own function to do what you want and override the function to call your new function instead.
Maybe I did not understood your question right but why not just copy this file into
app/code/**local**/Mage/Core/functions.php
and modify it there in any way you want?
As mentioned by #tweakmag the disadvantages of creating a folder structure and copying the entire Model or controller for a single function override, most important being,
"Future upgrades could introduce new features that would not be
available unless it is remembered to copy across the new version of
that file and implement the changes again."
Thus a solution can be, to extend the core class (Model or controller) and just write the method you want to override, instead of copying all the methods.
For example, if you want to say, override a method getProductCollection in Mage_Catalog_Model_Category, here will be the steps:
Create a Custom Namespace/Module folder with etc folder in it
Register the module in app/etc folder by creating Namespace_Module.xml
setup the config.xml in Namespace/Module/etc/ :
<?xml version="1.0"?>
<config>
<modules>
<Namespace_Module>
<version>1.0</version>
</Namespace_Module>
</modules>
<global>
<models>
<catalog>
<rewrite>
<category>Namespace_Module_Model_Category</category>
</rewrite>
</catalog>
</models>
</global>
</config>
create Model folder in Namespace_Module and a Php File Category.php
Now the main difference here is we extend the Magento's core class instead of writing all the methods
<?php
/**
* Catalog category model
*/
class Namespace_Module_Model_Category extends Mage_Catalog_Model_Category
{
public function getProductCollection()
{
// Include your custom code here!
$collection = Mage::getResourceModel('catalog/product_collection')
->setStoreId($this->getStoreId())
->addCategoryFilter($this);
return $collection;
}
}
The getProductCollection method is overridden so it'll be called instead of the method defined in the core model class.
Also an important point is:
When you override any methods in models, you should make sure that the data type of the return value of that method matches with the data type of the base class method. Since model methods are called from several core modules, we should make sure that it doesn't break other features!
This link gives a step by step approach to it
1. UOPZ
There's a way to do it without having to copy and maintain functions.php file from core, but it involves extension uopz (pecl install uopz), then you can rename magento's function (from foo to foo_uopzOLD for example) and define your own (https://secure.php.net/uopz)
It works and is very useful for magento - usually you'll bump into something you can not change. Uopz is very helpful in such cases.
pros: works ;), you don't have to redo it everytime you update Magento (if you do it right, because inside you still can call foo_uopzOLD so you can assure some backward compatibility... in some cases).
cons: it's little bit implicit
2. Composer post-install-cmd
If you don't like the above, but you use composer you can patch any file you want:
"scripts": {
"post-install-cmd": "patch -p0 < change-core-functions.patch"
}
pros: explicit (when patch fail - composer install fails), and since it's explicit - you can revisit and fix the patch every time you upgrade magento
cons: you have modified core file, so you probably would want to add it to .gitignore
3. Ugly solution (uglier than those above)
If none of the above is possible for you (really, give it a try with composer - there's no excuse for not using it). But when you really can not the only way I can think of
- create app/local/Mage/Core/functions.php
- define this one function you need
- load original /app/core/Mage/Core/functions.php
- surround every function foo() {...} with
if(!function_exists("foo"){
function foo() {...}
}
hold on to your chair and
eval this SOB ;)