586 lines
21 KiB
Java
586 lines
21 KiB
Java
/*
|
|
* Copyright 2008 The Closure Compiler Authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.google.javascript.jscomp;
|
|
|
|
import com.google.common.base.Joiner;
|
|
import com.google.common.collect.Lists;
|
|
import static com.google.javascript.jscomp.JsMessage.Style;
|
|
import static com.google.javascript.jscomp.JsMessage.Style.CLOSURE;
|
|
import static com.google.javascript.jscomp.JsMessage.Style.LEGACY;
|
|
import static com.google.javascript.jscomp.JsMessage.Style.RELAX;
|
|
import static com.google.javascript.jscomp.JsMessageVisitor.isLowerCamelCaseWithNumericSuffixes;
|
|
import static com.google.javascript.jscomp.JsMessageVisitor.toLowerCamelCaseWithNumericSuffixes;
|
|
import com.google.javascript.rhino.Node;
|
|
|
|
import junit.framework.TestCase;
|
|
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Test for {@link JsMessageVisitor}.
|
|
*
|
|
* @author anatol@google.com (Anatol Pomazau)
|
|
*/
|
|
public class JsMessageVisitorTest extends TestCase {
|
|
|
|
private Compiler compiler;
|
|
private List<JsMessage> messages;
|
|
private boolean allowLegacyMessages;
|
|
|
|
@Override
|
|
protected void setUp() throws Exception {
|
|
messages = Lists.newLinkedList();
|
|
allowLegacyMessages = true;
|
|
}
|
|
|
|
public void testJsMessageOnVar() {
|
|
extractMessagesSafely(
|
|
"/** @desc Hello */ var MSG_HELLO = goog.getMsg('a')");
|
|
assertEquals(0, compiler.getWarningCount());
|
|
assertEquals(1, messages.size());
|
|
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_HELLO", msg.getKey());
|
|
assertEquals("Hello", msg.getDesc());
|
|
}
|
|
|
|
public void testJsMessageOnProperty() {
|
|
extractMessagesSafely("/** @desc a */ " +
|
|
"pint.sub.MSG_MENU_MARK_AS_UNREAD = goog.getMsg('a')");
|
|
assertEquals(0, compiler.getWarningCount());
|
|
assertEquals(1, messages.size());
|
|
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_MENU_MARK_AS_UNREAD", msg.getKey());
|
|
assertEquals("a", msg.getDesc());
|
|
}
|
|
|
|
public void testOrphanedJsMessage() {
|
|
extractMessagesSafely("goog.getMsg('a')");
|
|
assertEquals(1, compiler.getWarningCount());
|
|
assertEquals(0, messages.size());
|
|
|
|
JSError warn = compiler.getWarnings()[0];
|
|
assertEquals(JsMessageVisitor.MESSAGE_NODE_IS_ORPHANED, warn.getType());
|
|
}
|
|
|
|
public void testMessageWithoutDescription() {
|
|
extractMessagesSafely("var MSG_HELLO = goog.getMsg('a')");
|
|
assertEquals(1, compiler.getWarningCount());
|
|
assertEquals(1, messages.size());
|
|
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_HELLO", msg.getKey());
|
|
|
|
assertEquals(JsMessageVisitor.MESSAGE_HAS_NO_DESCRIPTION,
|
|
compiler.getWarnings()[0].getType());
|
|
}
|
|
|
|
public void testIncorrectMessageReporting() {
|
|
extractMessages("var MSG_HELLO = goog.getMsg('a' + + 'b')");
|
|
assertEquals(1, compiler.getErrorCount());
|
|
assertEquals(0, compiler.getWarningCount());
|
|
assertEquals(0, messages.size());
|
|
|
|
JSError mailformedTreeError = compiler.getErrors()[0];
|
|
assertEquals(JsMessageVisitor.MESSAGE_TREE_MALFORMED,
|
|
mailformedTreeError.getType());
|
|
assertEquals("Message parse tree malformed. "
|
|
+ "STRING or ADD node expected; found: POS",
|
|
mailformedTreeError.description);
|
|
}
|
|
|
|
public void testEmptyMessage() {
|
|
// This is an edge case. Empty messages are useless, but shouldn't fail
|
|
extractMessagesSafely("var MSG_EMPTY = '';");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_EMPTY", msg.getKey());
|
|
assertEquals("", msg.toString());
|
|
}
|
|
|
|
public void testConcatOfStrings() {
|
|
extractMessagesSafely("var MSG_NOTEMPTY = 'aa' + 'bbb' \n + ' ccc';");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_NOTEMPTY", msg.getKey());
|
|
assertEquals("aabbb ccc", msg.toString());
|
|
}
|
|
|
|
public void testLegacyFormatDescription() {
|
|
extractMessagesSafely("var MSG_SILLY = 'silly test message';\n"
|
|
+ "var MSG_SILLY_HELP = 'help text';");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_SILLY", msg.getKey());
|
|
assertEquals("help text", msg.getDesc());
|
|
assertEquals("silly test message", msg.toString());
|
|
}
|
|
|
|
public void testLegacyFormatParametizedFunction() {
|
|
extractMessagesSafely("var MSG_SILLY = function(one, two) {"
|
|
+ " return one + ', ' + two + ', buckle my shoe';"
|
|
+ "};");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_SILLY", msg.getKey());
|
|
assertEquals(null, msg.getDesc());
|
|
assertEquals("{$one}, {$two}, buckle my shoe", msg.toString());
|
|
}
|
|
|
|
public void testLegacyMessageWithDescAnnotation() {
|
|
// Well, is was better do not allow legacy messages with @desc annotations,
|
|
// but people love to mix styles so we need to check @desc also.
|
|
extractMessagesSafely(
|
|
"/** @desc The description */ var MSG_A = 'The Message';");
|
|
|
|
assertEquals(1, messages.size());
|
|
assertEquals(1, compiler.getWarningCount());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_A", msg.getKey());
|
|
assertEquals("The Message", msg.toString());
|
|
assertEquals("The description", msg.getDesc());
|
|
}
|
|
|
|
public void testLegacyMessageWithDescAnnotationAndHelpVar() {
|
|
// Well, is was better do not allow legacy messages with @desc annotations,
|
|
// but people love to mix styles so we need to check @desc also.
|
|
extractMessagesSafely(
|
|
"var MSG_A_HELP = 'This is a help var';\n" +
|
|
"/** @desc The description in @desc*/ var MSG_A = 'The Message';");
|
|
|
|
assertEquals(1, messages.size());
|
|
assertEquals(1, compiler.getWarningCount());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_A", msg.getKey());
|
|
assertEquals("The Message", msg.toString());
|
|
assertEquals("The description in @desc", msg.getDesc());
|
|
}
|
|
|
|
public void testClosureMessageWithHelpPostfix() {
|
|
extractMessagesSafely("/** @desc help text */\n"
|
|
+ "var MSG_FOO_HELP = goog.getMsg('Help!');");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_FOO_HELP", msg.getKey());
|
|
assertEquals("help text", msg.getDesc());
|
|
assertEquals("Help!", msg.toString());
|
|
}
|
|
|
|
public void testClosureMessageWithoutGoogGetmsg() {
|
|
allowLegacyMessages = false;
|
|
|
|
extractMessages("var MSG_FOO_HELP = 'I am a bad message';");
|
|
|
|
assertEquals(1, messages.size());
|
|
assertEquals(1, compiler.getErrors().length);
|
|
JSError error = compiler.getErrors()[0];
|
|
assertEquals(JsMessageVisitor.MESSAGE_NOT_INITIALIZED_USING_NEW_SYNTAX,
|
|
error.getType());
|
|
}
|
|
|
|
public void testClosureFormatParametizedFunction() {
|
|
extractMessagesSafely("/** @desc help text */"
|
|
+ "var MSG_SILLY = goog.getMsg('{$adjective} ' + 'message', "
|
|
+ "{'adjective': 'silly'});");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_SILLY", msg.getKey());
|
|
assertEquals("help text", msg.getDesc());
|
|
assertEquals("{$adjective} message", msg.toString());
|
|
}
|
|
|
|
public void testHugeMessage() {
|
|
extractMessagesSafely("/**" +
|
|
" * @desc A message with lots of stuff.\n" +
|
|
" * @hidden\n" +
|
|
" */" +
|
|
"var MSG_HUGE = goog.getMsg(" +
|
|
" '{$startLink_1}Google{$endLink}' +" +
|
|
" '{$startLink_2}blah{$endLink}{$boo}{$foo_001}{$boo}' +" +
|
|
" '{$foo_002}{$xxx_001}{$image}{$image_001}{$xxx_002}'," +
|
|
" {'startLink_1': '<a href=http://www.google.com/>'," +
|
|
" 'endLink': '</a>'," +
|
|
" 'startLink_2': '<a href=\"' + opt_data.url + '\">'," +
|
|
" 'boo': opt_data.boo," +
|
|
" 'foo_001': opt_data.foo," +
|
|
" 'foo_002': opt_data.boo.foo," +
|
|
" 'xxx_001': opt_data.boo + opt_data.foo," +
|
|
" 'image': htmlTag7," +
|
|
" 'image_001': opt_data.image," +
|
|
" 'xxx_002': foo.callWithOnlyTopLevelKeys(" +
|
|
" bogusFn, opt_data, null, 'bogusKey1'," +
|
|
" opt_data.moo, 'bogusKey2', param10)});");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_HUGE", msg.getKey());
|
|
assertEquals("A message with lots of stuff.", msg.getDesc());
|
|
assertTrue(msg.isHidden());
|
|
assertEquals("{$startLink_1}Google{$endLink}{$startLink_2}blah{$endLink}" +
|
|
"{$boo}{$foo_001}{$boo}{$foo_002}{$xxx_001}{$image}" +
|
|
"{$image_001}{$xxx_002}", msg.toString());
|
|
}
|
|
|
|
public void testUnnamedGoogleMessage() {
|
|
extractMessagesSafely("var MSG_UNNAMED_2 = goog.getMsg('Hullo');");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals(null, msg.getDesc());
|
|
assertEquals("MSG_16LJMYKCXT84X", msg.getKey());
|
|
assertEquals("MSG_16LJMYKCXT84X", msg.getId());
|
|
}
|
|
|
|
public void testEmptyTextMessage() {
|
|
extractMessagesSafely("/** @desc text */ var MSG_FOO = goog.getMsg('');");
|
|
|
|
assertEquals(1, messages.size());
|
|
assertEquals(1, compiler.getWarningCount());
|
|
assertEquals("Message value of MSG_FOO is just an empty string. "
|
|
+ "Empty messages are forbidden.",
|
|
compiler.getWarnings()[0].description);
|
|
}
|
|
|
|
public void testEmptyTextComplexMessage() {
|
|
extractMessagesSafely("/** @desc text */ var MSG_BAR = goog.getMsg("
|
|
+ "'' + '' + '' + ''\n+'');");
|
|
|
|
assertEquals(1, messages.size());
|
|
assertEquals(1, compiler.getWarningCount());
|
|
assertEquals("Message value of MSG_BAR is just an empty string. "
|
|
+ "Empty messages are forbidden.",
|
|
compiler.getWarnings()[0].description);
|
|
}
|
|
|
|
public void testMessageIsNoUnnamed() {
|
|
extractMessagesSafely("var MSG_UNNAMED_ITEM = goog.getMsg('Hullo');");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_UNNAMED_ITEM", msg.getKey());
|
|
assertFalse(msg.isHidden());
|
|
}
|
|
|
|
public void testMsgVarWithoutAssignment() {
|
|
extractMessages("var MSG_SILLY;");
|
|
|
|
assertEquals(1, compiler.getErrors().length);
|
|
JSError error = compiler.getErrors()[0];
|
|
assertEquals(JsMessageVisitor.MESSAGE_HAS_NO_VALUE, error.getType());
|
|
}
|
|
|
|
public void testRegularVarWithoutAssignment() {
|
|
extractMessagesSafely("var SILLY;");
|
|
|
|
assertTrue(messages.isEmpty());
|
|
}
|
|
|
|
public void itIsNotImplementedYet_testMsgPropertyWithoutAssignment() {
|
|
extractMessages("goog.message.MSG_SILLY_PROP;");
|
|
|
|
assertEquals(1, compiler.getErrors().length);
|
|
JSError error = compiler.getErrors()[0];
|
|
assertEquals("Message MSG_SILLY_PROP has no value", error.description);
|
|
}
|
|
|
|
public void testMsgVarWithIncorrectRightSide() {
|
|
extractMessages("var MSG_SILLY = 0;");
|
|
|
|
assertEquals(1, compiler.getErrors().length);
|
|
JSError error = compiler.getErrors()[0];
|
|
assertEquals("Message parse tree malformed. Cannot parse value of "
|
|
+ "message MSG_SILLY", error.description);
|
|
}
|
|
|
|
public void testIncorrectMessage() {
|
|
extractMessages("DP_DatePicker.MSG_DATE_SELECTION = {};");
|
|
|
|
assertEquals(0, messages.size());
|
|
assertEquals(1, compiler.getErrors().length);
|
|
JSError error = compiler.getErrors()[0];
|
|
assertEquals("Message parse tree malformed. "+
|
|
"Message must be initialized using goog.getMsg function.",
|
|
error.description);
|
|
}
|
|
|
|
public void testUnrecognizedFunction() {
|
|
allowLegacyMessages = false;
|
|
extractMessages("DP_DatePicker.MSG_DATE_SELECTION = somefunc('a')");
|
|
|
|
assertEquals(0, messages.size());
|
|
assertEquals(1, compiler.getErrors().length);
|
|
JSError error = compiler.getErrors()[0];
|
|
assertEquals("Message parse tree malformed. "+
|
|
"Message initialized using unrecognized function. " +
|
|
"Please use goog.getMsg() instead.",
|
|
error.description);
|
|
}
|
|
|
|
public void testExtractPropertyMessage() {
|
|
extractMessagesSafely("/**"
|
|
+ " * @desc A message that demonstrates placeholders\n"
|
|
+ " * @hidden\n"
|
|
+ " */"
|
|
+ "a.b.MSG_SILLY = goog.getMsg(\n"
|
|
+ " '{$adjective} ' + '{$someNoun}',\n"
|
|
+ " {'adjective': adj, 'someNoun': noun});");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_SILLY", msg.getKey());
|
|
assertEquals("{$adjective} {$someNoun}", msg.toString());
|
|
assertEquals("A message that demonstrates placeholders", msg.getDesc());
|
|
assertTrue(msg.isHidden());
|
|
}
|
|
|
|
public void testAlmostButNotExternalMessage() {
|
|
extractMessagesSafely(
|
|
"/** @desc External */ var MSG_EXTERNAL = goog.getMsg('External');");
|
|
assertEquals(0, compiler.getWarningCount());
|
|
assertEquals(1, messages.size());
|
|
assertFalse(messages.get(0).isExternal());
|
|
assertEquals("MSG_EXTERNAL", messages.get(0).getKey());
|
|
}
|
|
|
|
public void testExternalMessage() {
|
|
extractMessagesSafely("var MSG_EXTERNAL_111 = goog.getMsg('Hello World');");
|
|
assertEquals(0, compiler.getWarningCount());
|
|
assertEquals(1, messages.size());
|
|
assertTrue(messages.get(0).isExternal());
|
|
assertEquals("111", messages.get(0).getId());
|
|
}
|
|
|
|
public void testIsValidMessageNameStrict() {
|
|
JsMessageVisitor visitor = new DummyJsVisitor(CLOSURE);
|
|
|
|
assertTrue(visitor.isMessageName("MSG_HELLO", true));
|
|
assertTrue(visitor.isMessageName("MSG_", true));
|
|
assertTrue(visitor.isMessageName("MSG_HELP", true));
|
|
assertTrue(visitor.isMessageName("MSG_FOO_HELP", true));
|
|
|
|
assertFalse(visitor.isMessageName("_FOO_HELP", true));
|
|
assertFalse(visitor.isMessageName("MSGFOOP", true));
|
|
}
|
|
|
|
public void testIsValidMessageNameRelax() {
|
|
JsMessageVisitor visitor = new DummyJsVisitor(RELAX);
|
|
|
|
assertFalse(visitor.isMessageName("MSG_HELP", false));
|
|
assertFalse(visitor.isMessageName("MSG_FOO_HELP", false));
|
|
}
|
|
|
|
public void testIsValidMessageNameLegacy() {
|
|
theseAreLegacyMessageNames(new DummyJsVisitor(RELAX));
|
|
theseAreLegacyMessageNames(new DummyJsVisitor(LEGACY));
|
|
}
|
|
|
|
private void theseAreLegacyMessageNames(JsMessageVisitor visitor) {
|
|
assertTrue(visitor.isMessageName("MSG_HELLO", false));
|
|
assertTrue(visitor.isMessageName("MSG_", false));
|
|
|
|
assertFalse(visitor.isMessageName("MSG_HELP", false));
|
|
assertFalse(visitor.isMessageName("MSG_FOO_HELP", false));
|
|
assertFalse(visitor.isMessageName("_FOO_HELP", false));
|
|
assertFalse(visitor.isMessageName("MSGFOOP", false));
|
|
}
|
|
|
|
public void testUnexistedPlaceholders() {
|
|
extractMessages("var MSG_FOO = goog.getMsg('{$foo}:', {});");
|
|
|
|
assertEquals(0, messages.size());
|
|
JSError[] errors = compiler.getErrors();
|
|
assertEquals(1, errors.length);
|
|
JSError error = errors[0];
|
|
assertEquals(JsMessageVisitor.MESSAGE_TREE_MALFORMED, error.getType());
|
|
assertEquals("Message parse tree malformed. Unrecognized message "
|
|
+ "placeholder referenced: foo", error.description);
|
|
}
|
|
|
|
public void testUnusedReferenesAreNotOK() {
|
|
extractMessages("/** @desc AA */ "
|
|
+ "var MSG_FOO = goog.getMsg('lalala:', {foo:1});");
|
|
assertEquals(0, messages.size());
|
|
JSError[] errors = compiler.getErrors();
|
|
assertEquals(1, errors.length);
|
|
JSError error = errors[0];
|
|
assertEquals(JsMessageVisitor.MESSAGE_TREE_MALFORMED, error.getType());
|
|
assertEquals("Message parse tree malformed. Unused message placeholder: "
|
|
+ "foo", error.description);
|
|
}
|
|
|
|
public void testDuplicatePlaceHoldersAreBad() {
|
|
extractMessages("var MSG_FOO = goog.getMsg("
|
|
+ "'{$foo}:', {'foo': 1, 'foo' : 2});");
|
|
|
|
assertEquals(0, messages.size());
|
|
JSError[] errors = compiler.getErrors();
|
|
assertEquals(1, errors.length);
|
|
JSError error = errors[0];
|
|
assertEquals(JsMessageVisitor.MESSAGE_TREE_MALFORMED, error.getType());
|
|
assertEquals("Message parse tree malformed. Duplicate placeholder "
|
|
+ "name: foo", error.description);
|
|
}
|
|
|
|
public void testDuplicatePlaceholderReferencesAreOk() {
|
|
extractMessagesSafely("var MSG_FOO = goog.getMsg("
|
|
+ "'{$foo}:, {$foo}', {'foo': 1});");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("{$foo}:, {$foo}", msg.toString());
|
|
}
|
|
|
|
public void testCamelcasePlaceholderNamesAreOk() {
|
|
extractMessagesSafely("var MSG_WITH_CAMELCASE = goog.getMsg("
|
|
+ "'Slide {$slideNumber}:', {'slideNumber': opt_index + 1});");
|
|
|
|
assertEquals(1, messages.size());
|
|
JsMessage msg = messages.get(0);
|
|
assertEquals("MSG_WITH_CAMELCASE", msg.getKey());
|
|
assertEquals("Slide {$slideNumber}:", msg.toString());
|
|
List<CharSequence> parts = msg.parts();
|
|
assertEquals(3, parts.size());
|
|
assertEquals("slideNumber",
|
|
((JsMessage.PlaceholderReference)parts.get(1)).getName());
|
|
}
|
|
|
|
public void testWithNonCamelcasePlaceholderNamesAreNotOk() {
|
|
extractMessages("var MSG_WITH_CAMELCASE = goog.getMsg("
|
|
+ "'Slide {$slide_number}:', {'slide_number': opt_index + 1});");
|
|
|
|
assertEquals(0, messages.size());
|
|
JSError[] errors = compiler.getErrors();
|
|
assertEquals(1, errors.length);
|
|
JSError error = errors[0];
|
|
assertEquals(JsMessageVisitor.MESSAGE_TREE_MALFORMED, error.getType());
|
|
assertEquals("Message parse tree malformed. Placeholder name not in "
|
|
+ "lowerCamelCase: slide_number", error.description);
|
|
}
|
|
|
|
public void testUnquotedPlaceholdersAreOk() {
|
|
extractMessagesSafely("/** @desc Hello */ "
|
|
+ "var MSG_FOO = goog.getMsg('foo {$unquoted}:', {unquoted: 12});");
|
|
|
|
assertEquals(1, messages.size());
|
|
assertEquals(0, compiler.getWarningCount());
|
|
}
|
|
|
|
public void testIsLowerCamelCaseWithNumericSuffixes() {
|
|
assertTrue(isLowerCamelCaseWithNumericSuffixes("name"));
|
|
assertFalse(isLowerCamelCaseWithNumericSuffixes("NAME"));
|
|
assertFalse(isLowerCamelCaseWithNumericSuffixes("Name"));
|
|
|
|
assertTrue(isLowerCamelCaseWithNumericSuffixes("a4Letter"));
|
|
assertFalse(isLowerCamelCaseWithNumericSuffixes("A4_LETTER"));
|
|
|
|
assertTrue(isLowerCamelCaseWithNumericSuffixes("startSpan_1_23"));
|
|
assertFalse(isLowerCamelCaseWithNumericSuffixes("startSpan_1_23b"));
|
|
assertFalse(isLowerCamelCaseWithNumericSuffixes("START_SPAN_1_23"));
|
|
|
|
assertFalse(isLowerCamelCaseWithNumericSuffixes(""));
|
|
}
|
|
|
|
public void testToLowerCamelCaseWithNumericSuffixes() {
|
|
assertEquals("name", toLowerCamelCaseWithNumericSuffixes("NAME"));
|
|
assertEquals("a4Letter", toLowerCamelCaseWithNumericSuffixes("A4_LETTER"));
|
|
assertEquals("startSpan_1_23",
|
|
toLowerCamelCaseWithNumericSuffixes("START_SPAN_1_23"));
|
|
}
|
|
|
|
public void testDuplicateMessageError() {
|
|
extractMessages(
|
|
"(function () {/** @desc Hello */ var MSG_HELLO = goog.getMsg('a')})" +
|
|
"(function () {/** @desc Hello2 */ var MSG_HELLO = goog.getMsg('a')})");
|
|
|
|
assertEquals(0, compiler.getWarningCount());
|
|
assertOneError(JsMessageVisitor.MESSAGE_DUPLICATE_KEY);
|
|
}
|
|
|
|
public void testNoDuplicateErrorOnExternMessage() {
|
|
extractMessagesSafely(
|
|
"(function () {/** @desc Hello */ " +
|
|
"var MSG_EXTERNAL_2 = goog.getMsg('a')})" +
|
|
"(function () {/** @desc Hello2 */ " +
|
|
"var MSG_EXTERNAL_2 = goog.getMsg('a')})");
|
|
}
|
|
|
|
public void testErrorWhenUsingMsgPrefixWithFallback() {
|
|
extractMessages(
|
|
"/** @desc Hello */ var MSG_HELLO_1 = goog.getMsg('hello');\n" +
|
|
"/** @desc Hello */ var MSG_HELLO_2 = goog.getMsg('hello');\n" +
|
|
"/** @desc Hello */ " +
|
|
"var MSG_HELLO_3 = goog.getMsgWithFallback(MSG_HELLO_1, MSG_HELLO_2);");
|
|
assertOneError(JsMessageVisitor.MESSAGE_TREE_MALFORMED);
|
|
}
|
|
|
|
private void assertOneError(DiagnosticType type) {
|
|
String errors = Joiner.on("\n").join(compiler.getErrors());
|
|
assertEquals("There should be one error. " + errors,
|
|
1, compiler.getErrorCount());
|
|
JSError error = compiler.getErrors()[0];
|
|
assertEquals(type, error.getType());
|
|
}
|
|
|
|
private void extractMessagesSafely(String input) {
|
|
extractMessages(input);
|
|
JSError[] errors = compiler.getErrors();
|
|
assertEquals(
|
|
"Unexpected error(s): " + Joiner.on("\n").join(compiler.getErrors()),
|
|
0, compiler.getErrorCount());
|
|
}
|
|
|
|
private void extractMessages(String input) {
|
|
compiler = new Compiler();
|
|
Node root = compiler.parseTestCode(input);
|
|
JsMessageVisitor visitor = new CollectMessages(compiler);
|
|
visitor.process(null, root);
|
|
}
|
|
|
|
private class CollectMessages extends JsMessageVisitor {
|
|
|
|
private CollectMessages(Compiler compiler) {
|
|
super(compiler, true, Style.getFromParams(true, allowLegacyMessages),
|
|
null);
|
|
}
|
|
|
|
@Override
|
|
protected void processJsMessage(JsMessage message,
|
|
JsMessageDefinition definition) {
|
|
messages.add(message);
|
|
}
|
|
}
|
|
|
|
private class DummyJsVisitor extends JsMessageVisitor {
|
|
|
|
private DummyJsVisitor(Style style) {
|
|
super(null, true, style, null);
|
|
}
|
|
|
|
@Override
|
|
protected void processJsMessage(JsMessage message,
|
|
JsMessageDefinition definition) {
|
|
// no-op
|
|
}
|
|
}
|
|
}
|