I want to suppress stylecop warnings for a method. So I added the following SuppressMessage:
[SuppressMessage("Microsoft.StyleCop.CSharp.Naming", "SA1306:FieldNamesMustBeginWithLowerCaseLetter", Justification = "MDS tables names need to be in capital letters")]
internal static class OffersDataProcessor
{
public static async Task<List<Offer>> RetrieveAndProcessOffersAsync(string BaseUrl, string baseUrlKey)
{
...
}
...
}
But this is still giving a warning on a console build:
D:\ProjectSolutionDir\ProjectSolution\Helpers\OffersDataProcessor.cs(26, 1): warning : SA1306 : CSharp.Naming : Variable names and private field names must start with a lower-case letter: BaseUrl. [D:\ProjectSolutionDir\ProjectSolution.csproj]
The line 26, 1 is where BaseUrl is present. Should I add something else to suppress the warnings?
The issue was an incorrect namespace. I had to use Microsoft.StyleCop.CSharp.NamingRules and not Microsoft.StyleCop.CSharp.Naming. That fixed the problem.
Related
I have a project with two targets representing two different final products. Until now the localization was shared between the two targets, but now I have just one string to be localized differently according to the active target. In order to avoid duplicating the Localizable.string file ad tweak the file target membership, I decided to create two different Localizable-Ext.string files containing just the string to be translated differently for each target.
I'm using the SwiftUI Text initializer accepting a LocalizedStringKey parameter which automatically looks up the corresponding translation inside the file. This is what has to be done in most cases. I noticed that this initializer also accepts a tableName parameter corresponding to the .string filename where the match should be taken.
What I'm trying to achieve is to have a custom Text initializer which takes the string key, looks up for it inside the default Localizable.string file and, if no match is found, falls back to the right file extension (string table) and search for it there. Apparently this is tough to achieve since I cannot manage to get the key value from the LocalizedStringKey instance.
I think you need something like
extension Text {
public init<S>(looking text: S) where S : StringProtocol {
let text = String(text)
var translated = NSLocalizedString(text, comment: "")
// returns same if no translation, so ...
if translated == text {
// ... continue in other table
translated = NSLocalizedString(text, tableName: "Localizable-Ext",
bundle: .main, value: text, comment: "")
}
// already translated, so avoid search again
self.init(verbatim: translated)
}
}
In the context of a Flutter 2.0.5 app whose state I'd like to manage with Riverpod, I thought I can declare a StateNotifierProvider like this:
import 'package:flutter_riverpod/flutter_riverpod.dart';
final counterProvider = StateNotifierProvider<CounterStateNotifier>((ref) => CounterStateNotifier());
class CounterStateNotifier extends StateNotifier<int> {
CounterStateNotifier([int count = 0]) : super(count);
void increment() => state++;
}
But Android Studio (and later the Dart compiler as well) complains about the line where I declare the counterProvider variable:
The type 'StateNotifierProvider' is declared with 2 type parameters, but 1 type arguments were given.
Removing the <CounterStateNotifier> type parameter in StateNotifierProvider<CounterStateNotifier> removes the error. However, attempting to read the provider and call its increment method (setting () => context.read(counterProvider).increment() as the onPressed of an ElevatedButton, then pressing the button) gives the following runtime error:
'increment'
method not found
Receiver: 0
Arguments: []
Why is context.read(counterProvider) returning the int state instead of the notifier? And what is the reason behind the type parameter error mentioned in the first part of my question?
I should mention that I'm running my app on the web (with flutter run -d Chrome).
As of Riverpod 0.14.0, State is the default value exposed by StateNotifierProvider.
The syntax for declaring your StateNotifierProvider is now as follows:
final counterProvider = StateNotifierProvider<CounterStateNotifier, int>((ref) => CounterStateNotifier());
Accessing functions now requires adding .notifier (accessing the StateNotifier itself):
context.read(counterProvider.notifier).increment();
And like you've noticed, you now access the state like so:
final count = context.read(counterProvider);
More on the changes here.
You may also use dynamic to accept any type if value for the StateNotifierProvider
final modelProvider =
StateNotifierProvider.autoDispose<ModelClassName, dynamic>(
(ref) => ModelClassName());
I am attempting to configure properties of a specific type and guaranteed not to be nil with getters. This works fine for String or URI instance variables, however when attempting to do the same thing with an HTTP::Client the compiler gives an error that the instance variable is not initialized in all initialize methods.
require "http/client"
class Server
getter uri : URI
getter foo : String
getter connnection : HTTP::Client
def initialize(#uri)
#foo = "Bar"
#connection = HTTP::Client.new #uri
end
end
The full error given by the compiler is:
Error in src/server.cr:6: expanding macro
getter connnection : HTTP::Client
^
in macro 'getter' expanded macro: macro_4613328608:113, line 4:
1.
2.
3.
> 4. #connnection : HTTP::Client
5.
6. def connnection : HTTP::Client
7. #connnection
8. end
9.
10.
11.
12.
instance variable '#connnection' of Server was not initialized directly in all of the 'initialize' methods, rendering it nilable. Indirect initialization is not supported.
How can I appropriately initialize the #connection instance variable so that the crystal compiler is happy?
You have a typo there:
require "http/client"
class Server
getter uri : URI
getter foo : String
getter connnection : HTTP::Client
# ^
def initialize(#uri)
#foo = "Bar"
#connection = HTTP::Client.new #uri
end
end
This works for me. As pointed out above you have a typo, so it's probably not even necessary to allow it to be nilable.
require "http/client"
class Server
getter uri : URI
getter foo : String
getter connection : HTTP::Client?
def initialize(#uri)
#foo = "Bar"
#connection = HTTP::Client.new #uri
end
end
Server.new(URI.parse("https://www.google.com"))
I've begun experimenting with ANTLR3 today. There seems to be a discrepency in the expressions that I use.
I want my class name to start with a capital letter, followed by mixed case letters and numbers. For instance, Car is valid, 8Car is invalid.
CLASS_NAME : ('A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*;
This works fine when I test it individually. However when I use it in the following rule,
model
: '~model' CLASS_NAME model_block
;
However, the CLASS_NAME begins to pick up class names beginning with numbers as well. In this case, ANTLR picks up Car, 8Car or even #Car as valid tokens. I'm missing something silly. Any pointers would be appreciated. Thanks.
CLASS_NAME will not match 8Car or #Car. You're probably using ANTLRWorks' interpreter (or the Eclipse plugin, which uses the same interpreter), which is printing errors on a UI tab you're not aware of, and displaying the incorrect chars in the tokens. Use ANTLRWorks' debugger instead, or write a small test class yourself:
T.g
grammar T;
parse : CLASS_NAME EOF;
CLASS_NAME : ('A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*;
Main.java
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
TLexer lexer = new TLexer(new ANTLRStringStream("8Car"));
TParser parser = new TParser(new CommonTokenStream(lexer));
parser.parse();
}
}
In short: I want to call a frontend block inside a model to get the output of the PHTML template.
I have a test.phtml template which generates content of a specific HTML file for my module. This HTML has to be generated only on administrator request so I call it inside a controller. And that controller calls model:
public function generateAction()
{
Mage::getSingleton('helloworld/sample')->doSomething();
}
Model looks like this:
class My_Helloworld_Model_Sample Mage_Core_Model_Abstract
{
public function doSomething()
{
$templatePath = 'helloworld/test.phtml';
$output = Mage::app()->getLayout()
->createBlock("core/template")
->setData('area','frontend')
->setTemplate($templatePath)
->toHtml();
//write $output in HTML file
}
//...
}
It calls block, gets the output of the test.phtml template file and writes it in HTML file.
Why I don't generate that HTML inside one of the models methods? Two reasons:
- user needs to have easy access to that file
- .phtml file is much more readable for user/designer
That's why I want to create a block to get its output. But the problem is that when I try to create that block, I get this error:
CRIT (2): Not valid template
file:frontend/base/default/template/test.phtml
Magento searches for the template inside the "base" theme. If I put that file there (frontend/base/default/template/test.phtml), then all works fine. But I'd like to keep that template inside the current theme's directory (where I keep the rest of the module's template files):
frontend/package/theme/template/test.phtml
How could I achieve this?
EDIT:
I'm sorry, I wanted to simplify the code to make it more readable. Here's where the template file is actually located:
frontend\default\modern\template\mymodule\test.phtml
After the button in the admin panel is clicked, controller calls model:
public function generateAction()
{
//Get model and call the method to generate HTML
Mage::getSingleton('mymodule/sample')->doSomething();
}
Model creates block to get output of the test.phtml template:
class My_Mymodule_Model_Sample Mage_Core_Model_Abstract
{
public function doSomething()
{
$templatePath = 'mymodule' . DS . 'test.phtml';
$output = Mage::app()->getLayout()
->createBlock("core/template")
->setData('area','frontend')
->setTemplate($templatePath)
->toHtml();
//write $output in HTML file
}
//...
}
Until now all works fine. But when the block is created, Magento can't find the template file, and gives me this error:
CRIT (2): Not valid template
file:frontend\ base\default \template\mymodule\test.phtml
After I added Mage::log in app/code/core/Mage/Core/Model/Design/Package.php, I got this info in the system.log file:
2012-09-06T09:40:55+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\ frontend\default\default \template\mymodule\test.phtml
2012-09-06T09:40:55+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\frontend\default\default\template\mymodule\test.phtml
2012-09-06T09:40:55+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\frontend\default\default\template\mymodule\test.phtml
2012-09-06T09:40:55+00:00 CRIT (2): Not valid template
file:frontend\base\default\template\mymodule\test.phtml
2012-09-06T09:40:56+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
2012-09-06T09:40:56+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
2012-09-06T09:40:56+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
If I modify the model method like this (comment out reference to frontend):
class My_Mymodule_Model_Sample Mage_Core_Model_Abstract
{
public function doSomething()
{
$templatePath = 'mymodule' . DS . 'test.phtml';
$output = Mage::app()->getLayout()
->createBlock("core/template")
//->setData('area','frontend') // <--removed
->setTemplate($templatePath)
->toHtml();
//write $output in HTML file
}
//...
}
I get this info in the system.log file:
2012-09-06T09:44:46+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\ adminhtml\default\default \template\mymodule\test.phtml
2012-09-06T09:44:46+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\template\mymodule\test.phtml
2012-09-06T09:44:46+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\template\mymodule\test.phtml
2012-09-06T09:44:46+00:00 CRIT (2): Not valid template
file:adminhtml\base\default\template\mymodule\test.phtml
2012-09-06T09:44:47+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
2012-09-06T09:44:47+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
2012-09-06T09:44:47+00:00 DEBUG (7):
E:\webserver\xampp\htdocs\magento\app\design\adminhtml\default\default\layout\local.xml
It seems that Magento doesn't care what theme is currently enabled and searches for the template in base theme. Is there any way to "tell" Magento which template should be used?
You've already have the answer, you've just misidentified the problem.
Magento only looks in the base package once it's looked for a file in the current theme. So first Magento will check
frontend/package/theme/template/test.phtml
THEN it will check
frontend/base/default/template/test.phtml
and if it still doesn't find anything, then it logs the error.
If you want to debug where Magento is trying to load the initial file from, add some temporary var_dump or Mage::Log debugging code to the design package file
#File: app/code/core/Mage/Core/Model/Design/Package.php
public function validateFile($file, array $params)
{
$fileName = $this->_renderFilename($file, $params);
$testFile = (empty($params['_relative']) ? '' : Mage::getBaseDir('design') . DS) . $fileName;
if (!file_exists($testFile)) {
var_dump($testFile);
Mage::Log($testFile);
return false;
}
return $fileName;
}
Also, include the actual code you're using on your system here and people will be better able to help you. There's a discrepancy between what you say you're setting your template path as
helloworld/test.phtml
and what you're actually setting is as (per the Magento errors)
test.phtml
Update: Based on what's in the additional logging, it looks like something is adding spaces to your template path, which means Magento can't find your template in it's initial location
E:\webserver\xampp\htdocs\magento\app\design\ frontend\default\default \template\mymodule\test.phtml
ex.
design\ frontend
\default \template
Also, I don't think it's the root cause, but don't use DS in template paths. PHP will take care of that fore you.