Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_langtools
提交
b9f5bce4
D
dragonwell8_langtools
项目概览
openanolis
/
dragonwell8_langtools
通知
0
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_langtools
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
b9f5bce4
编写于
11月 02, 2009
作者:
D
darcy
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6827009: Project Coin: Strings in Switch
Reviewed-by: jjg, mcimadamore
上级
c007cb57
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
886 addition
and
8 deletion
+886
-8
src/share/classes/com/sun/tools/javac/code/Source.java
src/share/classes/com/sun/tools/javac/code/Source.java
+3
-0
src/share/classes/com/sun/tools/javac/comp/Attr.java
src/share/classes/com/sun/tools/javac/comp/Attr.java
+23
-2
src/share/classes/com/sun/tools/javac/comp/Lower.java
src/share/classes/com/sun/tools/javac/comp/Lower.java
+189
-6
src/share/classes/com/sun/tools/javac/resources/compiler.properties
...classes/com/sun/tools/javac/resources/compiler.properties
+6
-0
test/tools/javac/StringsInSwitch/BadlyTypedLabel1.java
test/tools/javac/StringsInSwitch/BadlyTypedLabel1.java
+17
-0
test/tools/javac/StringsInSwitch/BadlyTypedLabel1.out
test/tools/javac/StringsInSwitch/BadlyTypedLabel1.out
+2
-0
test/tools/javac/StringsInSwitch/BadlyTypedLabel2.java
test/tools/javac/StringsInSwitch/BadlyTypedLabel2.java
+19
-0
test/tools/javac/StringsInSwitch/BadlyTypedLabel2.out
test/tools/javac/StringsInSwitch/BadlyTypedLabel2.out
+2
-0
test/tools/javac/StringsInSwitch/NonConstantLabel.java
test/tools/javac/StringsInSwitch/NonConstantLabel.java
+18
-0
test/tools/javac/StringsInSwitch/NonConstantLabel.out
test/tools/javac/StringsInSwitch/NonConstantLabel.out
+2
-0
test/tools/javac/StringsInSwitch/OneCaseSwitches.java
test/tools/javac/StringsInSwitch/OneCaseSwitches.java
+303
-0
test/tools/javac/StringsInSwitch/RSCL1.out
test/tools/javac/StringsInSwitch/RSCL1.out
+2
-0
test/tools/javac/StringsInSwitch/RSCL2.out
test/tools/javac/StringsInSwitch/RSCL2.out
+2
-0
test/tools/javac/StringsInSwitch/RepeatedStringCaseLabels1.java
...ools/javac/StringsInSwitch/RepeatedStringCaseLabels1.java
+17
-0
test/tools/javac/StringsInSwitch/RepeatedStringCaseLabels2.java
...ools/javac/StringsInSwitch/RepeatedStringCaseLabels2.java
+18
-0
test/tools/javac/StringsInSwitch/StringSwitches.java
test/tools/javac/StringsInSwitch/StringSwitches.java
+263
-0
未找到文件。
src/share/classes/com/sun/tools/javac/code/Source.java
浏览文件 @
b9f5bce4
...
...
@@ -110,6 +110,9 @@ public enum Source {
}
/** Allow encoding errors, giving only warnings. */
public
boolean
allowStringsInSwitch
()
{
return
compareTo
(
JDK1_7
)
>=
0
;
}
public
boolean
allowEncodingErrors
()
{
return
compareTo
(
JDK1_6
)
<
0
;
}
...
...
src/share/classes/com/sun/tools/javac/comp/Attr.java
浏览文件 @
b9f5bce4
...
...
@@ -115,6 +115,8 @@ public class Attr extends JCTree.Visitor {
allowBoxing
=
source
.
allowBoxing
();
allowCovariantReturns
=
source
.
allowCovariantReturns
();
allowAnonOuterThis
=
source
.
allowAnonOuterThis
();
allowStringsInSwitch
=
source
.
allowStringsInSwitch
();
sourceName
=
source
.
name
;
relax
=
(
options
.
get
(
"-retrofit"
)
!=
null
||
options
.
get
(
"-relax"
)
!=
null
);
useBeforeDeclarationWarning
=
options
.
get
(
"useBeforeDeclarationWarning"
)
!=
null
;
...
...
@@ -167,6 +169,16 @@ public class Attr extends JCTree.Visitor {
*/
boolean
enableSunApiLintControl
;
/**
* Switch: allow strings in switch?
*/
boolean
allowStringsInSwitch
;
/**
* Switch: name of source level; used for error reporting.
*/
String
sourceName
;
/** Check kind and type of given tree against protokind and prototype.
* If check succeeds, store type in tree and return it.
* If check fails, store errType in tree and return it.
...
...
@@ -886,7 +898,15 @@ public class Attr extends JCTree.Visitor {
boolean
enumSwitch
=
allowEnums
&&
(
seltype
.
tsym
.
flags
()
&
Flags
.
ENUM
)
!=
0
;
if
(!
enumSwitch
)
boolean
stringSwitch
=
false
;
if
(
types
.
isSameType
(
seltype
,
syms
.
stringType
))
{
if
(
allowStringsInSwitch
)
{
stringSwitch
=
true
;
}
else
{
log
.
error
(
tree
.
selector
.
pos
(),
"string.switch.not.supported.in.source"
,
sourceName
);
}
}
if
(!
enumSwitch
&&
!
stringSwitch
)
seltype
=
chk
.
checkType
(
tree
.
selector
.
pos
(),
seltype
,
syms
.
intType
);
// Attribute all cases and
...
...
@@ -909,7 +929,8 @@ public class Attr extends JCTree.Visitor {
Type
pattype
=
attribExpr
(
c
.
pat
,
switchEnv
,
seltype
);
if
(
pattype
.
tag
!=
ERROR
)
{
if
(
pattype
.
constValue
()
==
null
)
{
log
.
error
(
c
.
pat
.
pos
(),
"const.expr.req"
);
log
.
error
(
c
.
pat
.
pos
(),
(
stringSwitch
?
"string.const.req"
:
"const.expr.req"
));
}
else
if
(
labels
.
contains
(
pattype
.
constValue
()))
{
log
.
error
(
c
.
pos
(),
"duplicate.case.label"
);
}
else
{
...
...
src/share/classes/com/sun/tools/javac/comp/Lower.java
浏览文件 @
b9f5bce4
...
...
@@ -357,7 +357,7 @@ public class Lower extends TreeTranslator {
* case 2: stmt2
* }
* </pre>
* with the auxil
liary table in
tialized as follows:
* with the auxil
iary table ini
tialized as follows:
* <pre>
* class Outer$0 {
* synthetic final int[] $EnumMap$Color = new int[Color.values().length];
...
...
@@ -858,7 +858,7 @@ public class Lower extends TreeTranslator {
int
acode
;
// The access code of the access method.
List
<
Type
>
argtypes
;
// The argument types of the access method.
Type
restype
;
// The result type of the access method.
List
<
Type
>
thrown
;
// The thrown ex
e
ceptions of the access method.
List
<
Type
>
thrown
;
// The thrown exceptions of the access method.
switch
(
vsym
.
kind
)
{
case
VAR:
acode
=
accessCode
(
tree
,
enclOp
);
...
...
@@ -2463,7 +2463,7 @@ public class Lower extends TreeTranslator {
// the dead code, which will not be eliminated during code generation.
// Note that Flow.isFalse and Flow.isTrue only return true
// for constant expressions in the sense of JLS 15.27, which
// are guaranteed to have no side-effects. More agressive
// are guaranteed to have no side-effects. More ag
g
ressive
// constant propagation would require that we take care to
// preserve possible side-effects in the condition expression.
...
...
@@ -2850,7 +2850,7 @@ public class Lower extends TreeTranslator {
// If translated left hand side is an Apply, we are
// seeing an access method invocation. In this case, return
// that access method invo
k
ation as result.
// that access method invo
c
ation as result.
if
(
isUpdateOperator
&&
tree
.
arg
.
getTag
()
==
JCTree
.
APPLY
)
{
result
=
tree
.
arg
;
}
else
{
...
...
@@ -2900,7 +2900,7 @@ public class Lower extends TreeTranslator {
}
// where
/**
* A statment of the form
* A stat
e
ment of the form
*
* <pre>
* for ( T v : arrayexpr ) stmt;
...
...
@@ -3109,12 +3109,17 @@ public class Lower extends TreeTranslator {
Type
selsuper
=
types
.
supertype
(
tree
.
selector
.
type
);
boolean
enumSwitch
=
selsuper
!=
null
&&
(
tree
.
selector
.
type
.
tsym
.
flags
()
&
ENUM
)
!=
0
;
Type
target
=
enumSwitch
?
tree
.
selector
.
type
:
syms
.
intType
;
boolean
stringSwitch
=
selsuper
!=
null
&&
types
.
isSameType
(
tree
.
selector
.
type
,
syms
.
stringType
);
Type
target
=
enumSwitch
?
tree
.
selector
.
type
:
(
stringSwitch
?
syms
.
stringType
:
syms
.
intType
);
tree
.
selector
=
translate
(
tree
.
selector
,
target
);
tree
.
cases
=
translateCases
(
tree
.
cases
);
if
(
enumSwitch
)
{
result
=
visitEnumSwitch
(
tree
);
patchTargets
(
result
,
tree
,
result
);
}
else
if
(
stringSwitch
)
{
result
=
visitStringSwitch
(
tree
);
}
else
{
result
=
tree
;
}
...
...
@@ -3144,6 +3149,184 @@ public class Lower extends TreeTranslator {
return
make
.
Switch
(
selector
,
cases
.
toList
());
}
public
JCTree
visitStringSwitch
(
JCSwitch
tree
)
{
List
<
JCCase
>
caseList
=
tree
.
getCases
();
int
alternatives
=
caseList
.
size
();
if
(
alternatives
==
0
)
{
// Strange but legal possibility
return
make
.
at
(
tree
.
pos
()).
Exec
(
attr
.
makeNullCheck
(
tree
.
getExpression
()));
}
else
{
/*
* The general approach used is to translate a single
* string switch statement into a series of two chained
* switch statements: the first a synthesized statement
* switching on the argument string's hash value and
* computing a string's position in the list of original
* case labels, if any, followed by a second switch on the
* computed integer value. The second switch has the same
* code structure as the original string switch statement
* except that the string case labels are replaced with
* positional integer constants starting at 0.
*
* The first switch statement can be thought of as an
* inlined map from strings to their position in the case
* label list. An alternate implementation would use an
* actual Map for this purpose, as done for enum switches.
*
* With some additional effort, it would be possible to
* use a single switch statement on the hash code of the
* argument, but care would need to be taken to preserve
* the proper control flow in the presence of hash
* collisions and other complications, such as
* fallthroughs. Switch statements with one or two
* alternatives could also be specially translated into
* if-then statements to omit the computation of the hash
* code.
*
* The generated code assumes that the hashing algorithm
* of String is the same in the compilation environment as
* in the environment the code will run in. The string
* hashing algorithm in the SE JDK has been unchanged
* since at least JDK 1.2.
*/
ListBuffer
<
JCStatement
>
stmtList
=
new
ListBuffer
<
JCStatement
>();
// Map from String case labels to their original position in
// the list of case labels.
Map
<
String
,
Integer
>
caseLabelToPosition
=
new
LinkedHashMap
<
String
,
Integer
>(
alternatives
+
1
,
1.0f
);
// Map of hash codes to the string case labels having that hashCode.
Map
<
Integer
,
Set
<
String
>>
hashToString
=
new
LinkedHashMap
<
Integer
,
Set
<
String
>>(
alternatives
+
1
,
1.0f
);
int
casePosition
=
0
;
for
(
JCCase
oneCase
:
caseList
)
{
JCExpression
expression
=
oneCase
.
getExpression
();
if
(
expression
!=
null
)
{
// expression for a "default" case is null
String
labelExpr
=
(
String
)
expression
.
type
.
constValue
();
Integer
mapping
=
caseLabelToPosition
.
put
(
labelExpr
,
casePosition
);
assert
mapping
==
null
;
int
hashCode
=
labelExpr
.
hashCode
();
Set
<
String
>
stringSet
=
hashToString
.
get
(
hashCode
);
if
(
stringSet
==
null
)
{
stringSet
=
new
LinkedHashSet
<
String
>(
1
,
1.0f
);
stringSet
.
add
(
labelExpr
);
hashToString
.
put
(
hashCode
,
stringSet
);
}
else
{
boolean
added
=
stringSet
.
add
(
labelExpr
);
assert
added
;
}
}
casePosition
++;
}
// Synthesize a switch statement that has the effect of
// mapping from a string to the integer position of that
// string in the list of case labels. This is done by
// switching on the hashCode of the string followed by an
// if-then-else chain comparing the input for equality
// with all the case labels having that hash value.
/*
* s$ = top of stack;
* tmp$ = -1;
* switch($s.hashCode()) {
* case caseLabel.hashCode:
* if (s$.equals("caseLabel_1")
* tmp$ = caseLabelToPosition("caseLabel_1");
* else if (s$.equals("caseLabel_2"))
* tmp$ = caseLabelToPosition("caseLabel_2");
* ...
* break;
* ...
* }
*/
VarSymbol
dollar_s
=
new
VarSymbol
(
FINAL
|
SYNTHETIC
,
names
.
fromString
(
"s"
+
tree
.
pos
+
target
.
syntheticNameChar
()),
syms
.
stringType
,
currentMethodSym
);
stmtList
.
append
(
make
.
at
(
tree
.
pos
()).
VarDef
(
dollar_s
,
tree
.
getExpression
()).
setType
(
dollar_s
.
type
));
VarSymbol
dollar_tmp
=
new
VarSymbol
(
SYNTHETIC
,
names
.
fromString
(
"tmp"
+
tree
.
pos
+
target
.
syntheticNameChar
()),
syms
.
intType
,
currentMethodSym
);
JCVariableDecl
dollar_tmp_def
=
(
JCVariableDecl
)
make
.
VarDef
(
dollar_tmp
,
make
.
Literal
(
INT
,
-
1
)).
setType
(
dollar_tmp
.
type
);
dollar_tmp_def
.
init
.
type
=
dollar_tmp
.
type
=
syms
.
intType
;
stmtList
.
append
(
dollar_tmp_def
);
ListBuffer
<
JCCase
>
caseBuffer
=
ListBuffer
.
lb
();
// hashCode will trigger nullcheck on original switch expression
JCMethodInvocation
hashCodeCall
=
makeCall
(
make
.
Ident
(
dollar_s
),
names
.
hashCode
,
List
.<
JCExpression
>
nil
()).
setType
(
syms
.
intType
);
JCSwitch
switch1
=
make
.
Switch
(
hashCodeCall
,
caseBuffer
.
toList
());
for
(
Map
.
Entry
<
Integer
,
Set
<
String
>>
entry
:
hashToString
.
entrySet
())
{
int
hashCode
=
entry
.
getKey
();
Set
<
String
>
stringsWithHashCode
=
entry
.
getValue
();
assert
stringsWithHashCode
.
size
()
>=
1
;
JCStatement
elsepart
=
null
;
for
(
String
caseLabel
:
stringsWithHashCode
)
{
JCMethodInvocation
stringEqualsCall
=
makeCall
(
make
.
Ident
(
dollar_s
),
names
.
equals
,
List
.<
JCExpression
>
of
(
make
.
Literal
(
caseLabel
)));
elsepart
=
make
.
If
(
stringEqualsCall
,
make
.
Exec
(
make
.
Assign
(
make
.
Ident
(
dollar_tmp
),
make
.
Literal
(
caseLabelToPosition
.
get
(
caseLabel
))).
setType
(
dollar_tmp
.
type
)),
elsepart
);
}
ListBuffer
<
JCStatement
>
lb
=
ListBuffer
.
lb
();
JCBreak
breakStmt
=
make
.
Break
(
null
);
breakStmt
.
target
=
switch1
;
lb
.
append
(
elsepart
).
append
(
breakStmt
);
caseBuffer
.
append
(
make
.
Case
(
make
.
Literal
(
hashCode
),
lb
.
toList
()));
}
switch1
.
cases
=
caseBuffer
.
toList
();
stmtList
.
append
(
switch1
);
// Make isomorphic switch tree replacing string labels
// with corresponding integer ones from the label to
// position map.
ListBuffer
<
JCCase
>
lb
=
ListBuffer
.
lb
();
JCSwitch
switch2
=
make
.
Switch
(
make
.
Ident
(
dollar_tmp
),
lb
.
toList
());
for
(
JCCase
oneCase
:
caseList
)
{
// Rewire up old unlabeled break statements to the
// replacement switch being created.
patchTargets
(
oneCase
,
tree
,
switch2
);
boolean
isDefault
=
(
oneCase
.
getExpression
()
==
null
);
JCExpression
caseExpr
;
if
(
isDefault
)
caseExpr
=
null
;
else
{
caseExpr
=
make
.
Literal
(
caseLabelToPosition
.
get
((
String
)
oneCase
.
getExpression
().
type
.
constValue
()));
}
lb
.
append
(
make
.
Case
(
caseExpr
,
oneCase
.
getStatements
()));
}
switch2
.
cases
=
lb
.
toList
();
stmtList
.
append
(
switch2
);
return
make
.
Block
(
0L
,
stmtList
.
toList
());
}
}
public
void
visitNewArray
(
JCNewArray
tree
)
{
tree
.
elemtype
=
translate
(
tree
.
elemtype
);
for
(
List
<
JCExpression
>
t
=
tree
.
dims
;
t
.
tail
!=
null
;
t
=
t
.
tail
)
...
...
src/share/classes/com/sun/tools/javac/resources/compiler.properties
浏览文件 @
b9f5bce4
...
...
@@ -433,6 +433,8 @@ compiler.err.stack.sim.error=\
Internal error: stack sim error on {0}
compiler.err.static.imp.only.classes.and.interfaces
=
\
static import only from classes and interfaces
compiler.err.string.const.req
=
\
constant string expression required
compiler.err.synthetic.name.conflict
=
\
the symbol {0} conflicts with a compiler-synthesized symbol in {1}
compiler.warn.synthetic.name.conflict
=
\
...
...
@@ -1226,6 +1228,10 @@ compiler.err.diamond.not.supported.in.source=\
diamond operator is not supported in -source {0}
\n\
(use -source 7 or higher to enable diamond operator)
compiler.err.string.switch.not.supported.in.source
=
\
strings in switch are not supported in -source {0}
\n\
(use -source 7 or higher to enable strings in switch)
########################################
# Diagnostics for where clause implementation
# used by the RichDiagnosticFormatter.
...
...
test/tools/javac/StringsInSwitch/BadlyTypedLabel1.java
0 → 100644
浏览文件 @
b9f5bce4
/*
* @test /nodynamiccopyright/
* @bug 6827009
* @summary Check for case labels of different types.
* @compile/fail -source 6 BadlyTypedLabel1.java
* @compile/fail/ref=BadlyTypedLabel1.out -XDstdout -XDrawDiagnostics BadlyTypedLabel1.java
*/
class
BadlyTypedLabel1
{
String
m
(
String
s
)
{
switch
(
s
)
{
case
"Hello World"
:
return
(
s
);
case
42
:
return
(
"Don't forget your towel!"
);
}
}
}
test/tools/javac/StringsInSwitch/BadlyTypedLabel1.out
0 → 100644
浏览文件 @
b9f5bce4
BadlyTypedLabel1.java:13:14: compiler.err.prob.found.req: (compiler.misc.incompatible.types), int, java.lang.String
1 error
test/tools/javac/StringsInSwitch/BadlyTypedLabel2.java
0 → 100644
浏览文件 @
b9f5bce4
/*
* @test /nodynamiccopyright/
* @bug 6827009
* @summary Check for case lables of different types.
* @compile/fail -source 6 BadlyTypedLabel2.java
* @compile/fail/ref=BadlyTypedLabel2.out -XDstdout -XDrawDiagnostics BadlyTypedLabel2.java
*/
import
static
java
.
math
.
RoundingMode
.*;
class
BadlyTypedLabel2
{
String
m
(
String
s
)
{
switch
(
s
)
{
case
"Oh what a feeling..."
:
return
(
s
);
case
CEILING:
return
(
"... switching on the ceiling!"
);
}
}
}
test/tools/javac/StringsInSwitch/BadlyTypedLabel2.out
0 → 100644
浏览文件 @
b9f5bce4
BadlyTypedLabel2.java:15:14: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.math.RoundingMode, java.lang.String
1 error
test/tools/javac/StringsInSwitch/NonConstantLabel.java
0 → 100644
浏览文件 @
b9f5bce4
/*
* @test /nodynamiccopyright/
* @bug 6827009
* @summary Check for non-constant case labels.
* @compile/fail -source 6 NonConstantLabel.java
* @compile/fail/ref=NonConstantLabel.out -XDstdout -XDrawDiagnostics NonConstantLabel.java
*/
class
NonConstantLabel
{
String
m
(
String
s
)
{
String
fauxConstant
=
"Goodbye Cruel World"
;
switch
(
s
)
{
case
"Hello World"
:
return
(
s
);
case
fauxConstant:
return
(
s
+
s
);
}
}
}
test/tools/javac/StringsInSwitch/NonConstantLabel.out
0 → 100644
浏览文件 @
b9f5bce4
NonConstantLabel.java:14:14: compiler.err.string.const.req
1 error
test/tools/javac/StringsInSwitch/OneCaseSwitches.java
0 → 100644
浏览文件 @
b9f5bce4
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6827009
* @summary Positive tests for strings in switch with few alternatives.
* @compile/fail -source 6 OneCaseSwitches.java
* @compile OneCaseSwitches.java
* @run main OneCaseSwitches
* @author Joseph D. Darcy
*/
import
java.lang.reflect.*
;
import
java.lang.annotation.*
;
import
java.util.*
;
import
static
java
.
lang
.
annotation
.
RetentionPolicy
.*;
public
class
OneCaseSwitches
{
@Retention
(
RUNTIME
)
@interface
TestMeForNull
{}
@TestMeForNull
public
static
int
zeroCasesNoDefault
(
String
s
,
Set
<
String
>
stringSet
,
boolean
expected
)
{
int
failures
=
0
;
switch
(
s
)
{
}
return
failures
;
}
@TestMeForNull
public
static
int
zeroCasesWithDefault
(
String
s
,
Set
<
String
>
stringSet
,
boolean
expected
)
{
int
failures
=
2
;
boolean
addResult
;
switch
(
s
)
{
default
:
failures
=
0
;
addResult
=
stringSet
.
add
(
s
);
if
(
addResult
!=
expected
)
{
failures
++;
System
.
err
.
println
(
"zeroCaseWithDefault: Expectedly got add result of "
+
addResult
+
" on string "
+
s
);
}
}
return
failures
;
}
@TestMeForNull
public
static
int
zeroCasesWithDefaultBreak
(
String
s
,
Set
<
String
>
stringSet
,
boolean
expected
)
{
int
failures
=
2
;
boolean
addResult
;
switch
(
s
)
{
default
:
failures
=
zeroCasesWithDefault
(
s
,
stringSet
,
expected
);
break
;
}
return
failures
;
}
@TestMeForNull
public
static
int
oneCaseNoDefault
(
String
s
,
Set
<
String
>
stringSet
,
boolean
expected
)
{
int
failures
=
2
;
boolean
addResult
;
switch
(
s
)
{
case
"foo"
:
failures
=
0
;
addResult
=
stringSet
.
add
(
s
);
if
(
addResult
!=
expected
)
{
failures
++;
System
.
err
.
println
(
"oneCaseNoDefault: Unexpectedly got add result of "
+
addResult
+
" on string "
+
s
);
}
}
return
failures
;
}
@TestMeForNull
public
static
int
oneCaseNoDefaultBreak
(
String
s
,
Set
<
String
>
stringSet
,
boolean
expected
)
{
int
failures
=
2
;
boolean
addResult
;
switch
(
s
)
{
case
"foo"
:
failures
=
oneCaseNoDefaultBreak
(
s
,
stringSet
,
expected
);
break
;
}
return
failures
;
}
@TestMeForNull
public
static
int
oneCaseWithDefault
(
String
s
,
Set
<
String
>
stringSet
,
boolean
expected
)
{
int
failures
=
2
;
boolean
addResult
;;
switch
(
s
)
{
case
"foo"
:
failures
=
0
;
addResult
=
stringSet
.
add
(
s
);
if
(
addResult
!=
expected
)
{
failures
++;
System
.
err
.
println
(
"oneCaseNoDefault: Expectedly got add result of "
+
addResult
+
" on string "
+
s
);
}
break
;
default
:
break
;
}
return
failures
;
}
@TestMeForNull
public
static
int
oneCaseBreakOnly
(
String
s
,
Set
<
String
>
stringSet
,
boolean
expected
)
{
int
failures
=
1
;
switch
(
s
)
{
case
"foo"
:
break
;
}
failures
=
0
;
return
failures
;
}
@TestMeForNull
public
static
int
oneCaseDefaultBreakOnly
(
String
s
,
Set
<
String
>
stringSet
,
boolean
expected
)
{
int
failures
=
1
;
switch
(
s
)
{
default
:
break
;
}
failures
=
0
;
return
failures
;
}
static
int
testNullBehavior
()
{
int
failures
=
0
;
int
count
=
0
;
Method
[]
methods
=
OneCaseSwitches
.
class
.
getDeclaredMethods
();
try
{
for
(
Method
method
:
methods
)
{
count
++;
try
{
if
(
method
.
isAnnotationPresent
(
TestMeForNull
.
class
))
{
System
.
out
.
println
(
"Testing method "
+
method
);
method
.
invoke
(
null
,
(
String
)
null
,
emptyStringSet
,
false
);
failures
++;
System
.
err
.
println
(
"Didn't get NPE as expected from "
+
method
);
}
}
catch
(
InvocationTargetException
ite
)
{
// Expected
Throwable
targetException
=
ite
.
getTargetException
();
if
(!
(
targetException
instanceof
NullPointerException
))
{
failures
++;
// Wrong exception thrown
System
.
err
.
println
(
"Didn't get expected target exception NPE, got "
+
ite
.
getClass
().
getName
());
}
}
}
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
if
(
count
==
0
)
{
failures
++;
System
.
err
.
println
(
"Did not find any annotated methods."
);
}
return
failures
;
}
static
int
testZeroCases
()
{
int
failures
=
0
;
Set
<
String
>
noDefaultSet
=
new
HashSet
<
String
>();
Set
<
String
>
defaultSet
=
new
HashSet
<
String
>();
zeroCasesNoDefault
(
FOO
,
noDefaultSet
,
false
);
for
(
String
word
:
words
)
{
zeroCasesNoDefault
(
word
,
noDefaultSet
,
false
);
}
if
(!
noDefaultSet
.
isEmpty
())
{
failures
++;
System
.
err
.
println
(
"Non-empty set after zeroCasesNoDefault"
);
}
for
(
String
word
:
words
)
{
zeroCasesWithDefault
(
word
,
defaultSet
,
true
);
}
if
(
defaultSet
.
size
()
!=
words
.
length
)
{
failures
++;
System
.
err
.
println
(
"Missing strings after zeroCasesWithDefault"
);
}
return
failures
;
}
static
int
testOneCaseNoDefault
()
{
int
failures
=
0
;
Set
<
String
>
s
=
new
HashSet
<
String
>();
s
.
add
(
"foo"
);
Set
<
String
>
fooSet
=
Collections
.
unmodifiableSet
(
s
);
Set
<
String
>
testSet
=
new
HashSet
<
String
>();
oneCaseNoDefault
(
FOO
,
testSet
,
true
);
if
(!
testSet
.
equals
(
fooSet
))
{
failures
++;
System
.
err
.
println
(
"Unexpected result from oneCaseNoDefault: didn't get {\"Foo\"}"
);
}
for
(
String
word
:
words
)
{
oneCaseNoDefault
(
word
,
testSet
,
false
);
}
if
(!
testSet
.
equals
(
fooSet
))
{
failures
++;
System
.
err
.
println
(
"Unexpected result from oneCaseNoDefault: didn't get {\"Foo\"}"
);
}
return
failures
;
}
static
int
testBreakOnly
()
{
int
failures
=
0
;
for
(
String
word
:
words
)
{
failures
+=
oneCaseBreakOnly
(
word
,
emptyStringSet
,
true
);
failures
+=
oneCaseDefaultBreakOnly
(
word
,
emptyStringSet
,
true
);
}
return
failures
;
}
static
int
testExpressionEval
()
{
String
s
=
"a"
;
int
errors
=
2
;
System
.
out
.
println
(
"Testing expression evaluation."
);
switch
(
s
+
s
)
{
case
"aa"
:
errors
=
0
;
break
;
case
"aaaa"
:
errors
=
1
;
System
.
err
.
println
(
"Suspected bad expression evaluation."
);
break
;
default
:
throw
new
RuntimeException
(
"Should not reach here."
);
}
return
errors
;
}
static
final
String
FOO
=
"foo"
;
static
final
String
[]
words
=
{
"baz"
,
"quux"
,
"wombat"
,
"\u0ccc\u0012"
};
// hash collision with "foo"
final
static
Set
<
String
>
emptyStringSet
=
Collections
.
emptySet
();
public
static
void
main
(
String
...
args
)
{
int
failures
=
0
;
failures
+=
testNullBehavior
();
failures
+=
testZeroCases
();
failures
+=
testOneCaseNoDefault
();
failures
+=
testBreakOnly
();
failures
+=
testExpressionEval
();
if
(
failures
>
0
)
{
throw
new
RuntimeException
();
}
}
}
test/tools/javac/StringsInSwitch/RSCL1.out
0 → 100644
浏览文件 @
b9f5bce4
RepeatedStringCaseLabels1.java:13:9: compiler.err.duplicate.case.label
1 error
test/tools/javac/StringsInSwitch/RSCL2.out
0 → 100644
浏览文件 @
b9f5bce4
RepeatedStringCaseLabels2.java:14:9: compiler.err.duplicate.case.label
1 error
test/tools/javac/StringsInSwitch/RepeatedStringCaseLabels1.java
0 → 100644
浏览文件 @
b9f5bce4
/*
* @test /nodynamiccopyright/
* @bug 6827009
* @summary Check for repeated string case labels.
* @compile/fail -source 6 RepeatedStringCaseLabels1.java
* @compile/fail/ref=RSCL1.out -XDstdout -XDrawDiagnostics RepeatedStringCaseLabels1.java
*/
class
RepeatedStringCaseLabels1
{
String
m
(
String
s
)
{
switch
(
s
)
{
case
"Hello World"
:
return
(
s
);
case
"Hello"
+
" "
+
"World"
:
return
(
s
+
s
);
}
}
}
test/tools/javac/StringsInSwitch/RepeatedStringCaseLabels2.java
0 → 100644
浏览文件 @
b9f5bce4
/*
* @test /nodynamiccopyright/
* @bug 6827009
* @summary Check for repeated string case labels.
* @compile/fail -source 6 RepeatedStringCaseLabels2.java
* @compile/fail/ref=RSCL2.out -XDstdout -XDrawDiagnostics RepeatedStringCaseLabels2.java
*/
class
RepeatedStringCaseLabels2
{
String
m
(
String
s
)
{
final
String
constant
=
"Hello"
+
" "
+
"World"
;
switch
(
s
)
{
case
"Hello World"
:
return
(
s
);
case
constant:
return
(
s
+
s
);
}
}
}
test/tools/javac/StringsInSwitch/StringSwitches.java
0 → 100644
浏览文件 @
b9f5bce4
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6827009
* @summary Positive tests for strings in switch.
* @author Joseph D. Darcy
*/
public
class
StringSwitches
{
public
static
void
main
(
String
...
args
)
{
int
failures
=
0
;
failures
+=
testPileup
();
failures
+=
testSwitchingTwoWays
();
failures
+=
testNamedBreak
();
if
(
failures
>
0
)
{
throw
new
RuntimeException
();
}
}
/*
* A zero length string and all strings consisting only of the
* zero character \u0000 have a hash code of zero. This method
* maps such strings to the number of times \u0000 appears for 0
* through 6 occurrences.
*/
private
static
int
zeroHashes
(
String
s
)
{
int
result
=
Integer
.
MAX_VALUE
;
switch
(
s
)
{
case
""
:
return
0
;
case
"\u0000"
:
result
=
1
;
break
;
case
"\u0000\u0000"
:
return
2
;
case
"\u0000\u0000\u0000"
:
result
=
3
;
break
;
case
"\u0000\u0000\u0000\u0000"
:
return
4
;
case
"\u0000\u0000\u0000\u0000\u0000"
:
result
=
5
;
break
;
case
"\u0000\u0000\u0000\u0000\u0000\u0000"
:
return
6
;
default
:
result
=
-
1
;
}
return
result
;
}
private
static
int
testPileup
()
{
int
failures
=
0
;
String
zero
=
""
;
for
(
int
i
=
0
;
i
<=
6
;
i
++,
zero
+=
"\u0000"
)
{
int
result
=
zeroHashes
(
zero
);
if
(
result
!=
i
)
{
failures
++;
System
.
err
.
printf
(
"For string \"%s\" unexpectedly got %d instead of %d%n."
,
zero
,
result
,
i
);
}
}
if
(
zeroHashes
(
"foo"
)
!=
-
1
)
{
failures
++;
System
.
err
.
println
(
"Failed to get -1 for input string."
);
}
return
failures
;
}
/**
* Verify that a switch on an enum and a switch with the same
* structure on the string name of an enum compute equivalent
* values.
*/
private
static
int
testSwitchingTwoWays
()
{
int
failures
=
0
;
for
(
MetaSynVar
msv
:
MetaSynVar
.
values
())
{
int
enumResult
=
enumSwitch
(
msv
);
int
stringResult
=
stringSwitch
(
msv
.
name
());
if
(
enumResult
!=
stringResult
)
{
failures
++;
System
.
err
.
printf
(
"One value %s, computed 0x%x with the enum switch "
+
"and 0x%x with the string one.%n"
,
msv
,
enumResult
,
stringResult
);
}
}
return
failures
;
}
private
static
enum
MetaSynVar
{
FOO
,
BAR
,
BAZ
,
QUX
,
QUUX
,
QUUUX
,
MUMBLE
,
FOOBAR
;
}
private
static
int
enumSwitch
(
MetaSynVar
msv
)
{
int
result
=
0
;
switch
(
msv
)
{
case
FOO:
result
|=
(
1
<<
0
);
// fallthrough:
case
BAR:
case
BAZ:
result
|=
(
1
<<
1
);
break
;
default
:
switch
(
msv
)
{
case
QUX:
result
|=
(
1
<<
2
);
break
;
case
QUUX:
result
|=
(
1
<<
3
);
default
:
result
|=
(
1
<<
4
);
}
result
|=
(
1
<<
5
);
break
;
case
MUMBLE:
result
|=
(
1
<<
6
);
return
result
;
case
FOOBAR:
result
|=
(
1
<<
7
);
break
;
}
result
|=
(
1
<<
8
);
return
result
;
}
private
static
int
stringSwitch
(
String
msvName
)
{
int
result
=
0
;
switch
(
msvName
)
{
case
"FOO"
:
result
|=
(
1
<<
0
);
// fallthrough:
case
"BAR"
:
case
"BAZ"
:
result
|=
(
1
<<
1
);
break
;
default
:
switch
(
msvName
)
{
case
"QUX"
:
result
|=
(
1
<<
2
);
break
;
case
"QUUX"
:
result
|=
(
1
<<
3
);
default
:
result
|=
(
1
<<
4
);
}
result
|=
(
1
<<
5
);
break
;
case
"MUMBLE"
:
result
|=
(
1
<<
6
);
return
result
;
case
"FOOBAR"
:
result
|=
(
1
<<
7
);
break
;
}
result
|=
(
1
<<
8
);
return
result
;
}
private
static
int
testNamedBreak
()
{
int
failures
=
0
;
String
[]
testStrings
=
{
"a"
,
"b"
,
"c"
,
"d"
,
"e"
};
int
[]
testExpected
=
{
0b101011
,
0b101
,
0b100001
,
0b101000
,
0b10000
};
for
(
int
i
=
0
;
i
<
testStrings
.
length
;
i
++)
{
int
expected
=
testExpected
[
i
];
int
result
=
namedBreak
(
testStrings
[
i
]);
if
(
result
!=
expected
)
{
failures
++;
System
.
err
.
printf
(
"On input %s, got %d instead of %d.%n"
,
testStrings
[
i
],
result
,
expected
);
}
}
return
failures
;
}
private
static
int
namedBreak
(
String
s
)
{
int
result
=
0
;
outer:
switch
(
s
)
{
case
"a"
:
case
"b"
:
case
"c"
:
result
|=
(
1
<<
0
);
inner:
switch
(
s
+
s
)
{
case
"aa"
:
result
|=
(
1
<<
1
);
break
inner
;
case
"cc"
:
break
outer
;
default
:
result
|=
(
1
<<
2
);
return
result
;
}
case
"d"
:
result
|=
(
1
<<
3
);
break
outer
;
default
:
return
result
|=
(
1
<<
4
);
}
result
|=
(
1
<<
5
);
return
result
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录