In PhpStorm (and other JetBrains IDE), is it possible to make function attributes as file / resource path?
E.g. in this function:
function mix($file): string
{
// check mix maninfest for $file and return path from mix manifest
return $fire_path_with_cachebuster;
}
I'd like PHP to suggest files in the project as I define $file attribute when calling mix function.
Only manually for the moment, when calling that function 😒. And it's a temp injection (for a session) so it's not convenient:
mix('')
Place caret inside the string parameter
Use Alt + Enter (or via light bulb icon) to bring the Quick Fix / Intentions menu (on some Keymaps it might be different one)
Use "Inject language or reference" option
Then choose "File Reference" entry there (just start typing to filter the list).
The result:
Hopefully they will implement the following tickets for a permanent solution:
Using #[Language] PHP attribute at the function declaration: https://youtrack.jetbrains.com/issue/WI-56996
Or in-place via PHPDoc-like comment (before the parameter when calling that function): https://youtrack.jetbrains.com/issue/WI-20028
Watch those tickets (star/vote/comment) to get notified on any progress (and hopefully speed it up by bringing dev's attention).
Like LazyOne stated, there is currently no way to declare a parameter as being a file reference.
However, you can get a more permanent File Reference "injection" by [mis]using __DIR__.
PhpStorm considers a string mixed with the __DIR__ constant to be a file path:
It isn't perfect as it depends on what directory you are currently located in. If you only want the filename passed to your method, you can wrap the string in basename, or handle that from within your method.
echo mix(basename(__DIR__ . '/slack_bot.php'));
Related
I am using a userFunction to query the property database in a custom Forge Viewer extension. This works great while testing the site locally using npm run serve. However, when I deploy the website to the web (which uses npm run build), the function no longer executes. The error says: SyntaxError: Function statements require a function name. This is because, according to the documentation, the function executed through executeUserFunction has to be named userFunction.
Upon further inspection I discovered that this was because of Vue & Webpack's mangling feature (executed by terser-webpack-plugin), where it renames variables and removes function names to decrease file size.
I have tried many different things, from making the function part of the extension's class to moving it to the global JS scope, but nothing helped. I also tried to exclude objects.js (which is the name of the extension I wrote) from mangling, but this didn't work either.
How do I configure terser to stop mangling this one variable?
I eventually figured out a way to do this which worked:
Add the following to vue.config.js:
module.exports = {
...
chainWebpack: config => {
config.optimization.minimizer('terser').tap(args => {
// eslint-disable-next-line no-param-reassign
args[0].terserOptions.keep_fnames = true;
return args;
});
},
};
This will prevent terser from removing function names, and will make it so userFunction still works. Weird design choice by Autodesk to require a function name, but at least it works now :)
In ASP.NET Core, the JsonConfigurationProvider will load configuration from appsettings.json, and then will read in the environment version, appsettings.{Environment}.json, based on what IHostingEnvironment.EnvironmentName is. The environment version can override the values of the base appsettings.json.
Is there any reasonable way to preview what the resulting overridden configuration looks like?
Obviously, you could write unit tests that explicitly test that elements are overridden to your expectations, but that would be a very laborious workaround with upkeep for every time you change a setting. It's not a good solution if you just wanted to validate that you didn't misplace a bracket or misspell an element name.
Back in ASP.NET's web.config transforms, you could simply right-click on a transform in Visual Studio and choose "Preview Transform". There are also many other ways to preview an XSLT transform outside of Visual Studio. Even for web.config parameterization with Parameters.xml, you could at least execute Web Deploy and review the resulting web.config to make sure it came out right.
There does not seem to be any built-in way to preview appsettings.{Environment}.json's effects on the base file in Visual Studio. I haven't been able to find anything outside of VS to help with this either. JSON overriding doesn't appear to be all that commonplace, even though it is now an integral part of ASP.NET Core.
I've figured out you can achieve a preview with Json.NET's Merge function after loading the appsettings files into JObjects.
Here's a simple console app demonstrating this. Provide it the path to where your appsettings files are and it will emit previews of how they'll look in each environment.
static void Main(string[] args)
{
string targetPath = #"C:\path\to\my\app";
// Parse appsettings.json
var baseConfig = ParseAppSettings($#"{targetPath}\appsettings.json");
// Find all appsettings.{env}.json's
var regex = new Regex(#"appsettings\..+\.json");
var environmentConfigs = Directory.GetFiles(targetPath, "*.json")
.Where(path => regex.IsMatch(path));
foreach (var env in environmentConfigs)
{
// Parse appsettings.{env}.json
var transform = ParseAppSettings(env);
// Clone baseConfig since Merge is a void operation
var result = (JObject)baseConfig.DeepClone();
// Merge the two, making sure to overwrite arrays
result.Merge(transform, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Replace
});
// Write the preview to file
string dest = $#"{targetPath}\preview-{Path.GetFileName(env)}";
File.WriteAllText(dest, result.ToString());
}
}
private static JObject ParseAppSettings(string path)
=> JObject.Load(new JsonTextReader(new StreamReader(path)));
While this is no guarantee there won't be some other config source won't override these once deployed, this will at least let you validate that the interactions between these two files will be handled correctly.
There's not really a way to do that, but I think a bit about how this actually works would help you understand why.
With config transforms, there was literal file modification, so it's easy enough to "preview" that, showing the resulting file. The config system in ASP.NET Core is completely different.
It's basically just a dictionary. During startup, each registered configuration provider is run in the order it was registered. The provider reads its configuration source, whether that be a JSON file, system environment variables, command line arguments, etc. and builds key-value pairs, which are then added to the main configuration "dictionary". An "override", such as appsettings.{environment}.json, is really just another JSON provider registered after the appsettings.json provider, which obviously uses a different source (JSON file). Since it's registered after, when an existing key is encountered, its value is overwritten, as is typical for anything being added to a dictionary.
In other words, the "preview" would be completed configuration object (dictionary), which is composed of a number of different sources, not just these JSON files, and things like environment variables or command line arguments will override even the environment-specific JSON (since they're registered after that), so you still wouldn't technically know the the environment-specific JSON applied or not, because the value could be coming from another source that overrode that.
You can use the GetDebugView extension method on the IConfigurationRoot with something like
app.UseEndpoints(endpoints =>
{
if(env.IsDevelopment())
{
endpoints.MapGet("/config", ctx =>
{
var config = (Configuration as IConfigurationRoot).GetDebugView();
return ctx.Response.WriteAsync(config);
});
}
});
However, doing this can impose security risks, as it'll expose all your configuration like connection strings so you should enable this only in development.
You can refer to this article by Andrew Lock to understand how it works: https://andrewlock.net/debugging-configuration-values-in-aspnetcore/
Background
I use several helper functions to stop the program flow and return data. For example, while most pages are HTML I occasionally return JSON and call
/**
* #param array|bool $response
*
* #die
*/
function jsonResponseDie($response)
{
header('Content-Type: application/json');
echo json_encode($response);
die();
}
The Problem
However, the calling function does not detect that there is a die statement and allows code to be present after it without warning.
function recievePush()
{
// Process a push request and respond with a json array.
jsonResponseDie(array('status' => TRUE));
echo 'This will never execute but PhpStorm doesn\'t know that';
}
The Question
How do I get PhpStorm to detect this function will die?
I did try a few items "#return die" or "#die" but these do not appear to be recognized. I also reviewed some documentation here but found nothing useful.
There is no special tags for such stuff in PHPDoc. PhpStorm also does not have any solution to that yet.
https://youtrack.jetbrains.com/issue/WI-10673 -- watch this ticket (star/vote/comment) to get notified on any progress.
UPDATE 2020-10-20:
The aforementioned ticket has been implemented and such functionality is now available since PhpStorm 2020.1.x version.
It is implemented using Advanced Metadata functionality (by creating separate PHP-like file for IDE eyes only): https://www.jetbrains.com/help/phpstorm/ide-advanced-metadata.html#define-exit-points
<?php
namespace PHPSTORM_META {
exitPoint(\App\PageFlow::exitApplication());
}
Another example: as a result, the terminate() call with the bar argument provided will act as an exit point (another value will not trigger this). The last line of the run method will therefore be treated as unreachable:
exitPoint(Application::terminate('bar'));
P.S. From PhpStorm 2020.3 (to be released at some point in December or so this year) and using PHP Language Level = 8.0 you will be able to use PHP 8-style attribute #[NoReturn] right in your code instead of separate Advanced Metadata file (see WI-55531 (actual/original implementation) and WI-56103 (new attribute name) tickets).
I have a CodeIgniter 3.1.11 project that I wanted to implement an exitPoint on my SendJsonResponseAndDie() method which is in my myproject/ci/application/helpers/format_helper.php file.
For me, the solution was as simple as creating a meta directory in myproject, then creating a .phpstorm.meta.php file with the following contents:
myproject/meta/.phpstorm.meta.php:
<?php
namespace PHPSTORM_META {
function exitPoint($functionReference) {
return "exitPoint " . $functionReference;
}
exitPoint(\SendJsonResponseAndDie());
}
Hey presto, the "unreachable statement" text appears whenever I mouseover code that occurs after the function call anywhere in the project.
I wish, though, that the lines of code that cannot be reached would be dimmed so that I am visually drawn to the problem instead of requiring my hover event.
Some additional reading not mentioned in #LazyOne's answer: https://github.com/JetBrains/phpstorm-stubs/blob/master/meta/.phpstorm.meta.php
I use doxygen to document C++ code. In the current project, I use the following format for function signatures:
MyClass(MyClass&& other)
However, in the generated HTML documentation, the brief description has this signature:
MyClass (MyClass &&other)
and the detailed description has this signature:
MyClass ( MyClass && other )
Is there a way of either preserving the original format, or changing the way doxygen formats the signatures? I have not found anything related to this issue in the customization or configuration pages.
Edit: Updated the signatures based on the discussion in the comments.
Short answer: No.
Long (and more correct) answer: Yes, if you're willing to modify the source code.
File memberdef.cpp has the following (line 1668 in what I'm looking at today):
// *** write arguments
if (argsString() && !isObjCMethod())
{
if (!isDefine() && !isTypedef()) ol.writeString(" ");
That last line is going to add space in the brief description. (I've verified this by removing it and recompiling.)
As for the detailed description, that sets up a table, with <td>(</td> opening the arguments list. You might get rid of that space more easily, but doing it well will probably require monkeying with the source code.
I guess the best option is to roll your own, or to request a feature addition from the developers.
I've seen that some projects used _ function that takes string as an argument, like _("Hello World"). But I couldn't find any manuals or articles about what is it and how to use it.
I guess this has something to do with i18n and l10n (it was mentioned in some article I found on the internet), but can you explain to me how it works and how to use it?
That is the GNU gettext localization function. You can provide language specific alternate strings for the one specified in the function call.
There is the xgettext tool, which generates a .pot file (abbreviation for portable object template) from your application code, then translators can make .po localization files for it. Then, you can bundle these with your application, and deliver a more widely usable piece of software.
I18n. See gettext example here: https://ewgeny.wordpress.com/2012/05/10/supporting-multiple-languages-in-your-application-a-simple-gettext-step-by-step-example/
Also found some info about what exactly this function do, it seems to be the macro for Glib.dgettext() function in Vala, this is from valadoc.org:
dgettext
public unowned string dgettext (string? domain, string msgid)
This function is a wrapper of dgettext which does not translate the message if the default domain as set with textdomain has no translations for the current locale.
...
Applications should normally not use this function directly, but use the _ macro for translations.