mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
8003967: detect and remove all mutable implicit static enum fields in langtools
Reviewed-by: jjg
This commit is contained in:
parent
5c0bff8f21
commit
8fc2d739bd
31 changed files with 333 additions and 128 deletions
|
@ -448,10 +448,10 @@ public enum Opcode {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Opcode[] stdOpcodes = new Opcode[256];
|
private static final Opcode[] stdOpcodes = new Opcode[256];
|
||||||
private static Opcode[] wideOpcodes = new Opcode[256];
|
private static final Opcode[] wideOpcodes = new Opcode[256];
|
||||||
private static Opcode[] nonPrivOpcodes = new Opcode[256];
|
private static final Opcode[] nonPrivOpcodes = new Opcode[256];
|
||||||
private static Opcode[] privOpcodes = new Opcode[256];
|
private static final Opcode[] privOpcodes = new Opcode[256];
|
||||||
static {
|
static {
|
||||||
for (Opcode o: values())
|
for (Opcode o: values())
|
||||||
getOpcodeBlock(o.opcode >> 8)[o.opcode & 0xff] = o;
|
getOpcodeBlock(o.opcode >> 8)[o.opcode & 0xff] = o;
|
||||||
|
|
|
@ -46,7 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.Configuration;
|
||||||
* @since 1.8
|
* @since 1.8
|
||||||
*/
|
*/
|
||||||
abstract class DocFileFactory {
|
abstract class DocFileFactory {
|
||||||
private static Map<Configuration, DocFileFactory> factories =
|
private static final Map<Configuration, DocFileFactory> factories =
|
||||||
new WeakHashMap<Configuration, DocFileFactory>();
|
new WeakHashMap<Configuration, DocFileFactory>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -49,7 +49,7 @@ class Server implements Runnable {
|
||||||
private final OutputStream out;
|
private final OutputStream out;
|
||||||
private final boolean isSocket;
|
private final boolean isSocket;
|
||||||
private static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
|
private static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
|
||||||
private static Logger logger = Logger.getLogger("com.sun.tools.javac");
|
private static final Logger logger = Logger.getLogger("com.sun.tools.javac");
|
||||||
static class CwdFileManager extends ForwardingJavaFileManager<JavaFileManager> {
|
static class CwdFileManager extends ForwardingJavaFileManager<JavaFileManager> {
|
||||||
String cwd;
|
String cwd;
|
||||||
CwdFileManager(JavaFileManager fileManager) {
|
CwdFileManager(JavaFileManager fileManager) {
|
||||||
|
@ -69,7 +69,7 @@ class Server implements Runnable {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
// static CwdFileManager fm = new CwdFileManager(tool.getStandardFileManager());
|
// static CwdFileManager fm = new CwdFileManager(tool.getStandardFileManager());
|
||||||
static StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
|
static final StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
|
||||||
static {
|
static {
|
||||||
// Use the same file manager for all compilations. This will
|
// Use the same file manager for all compilations. This will
|
||||||
// cache jar files in the standard file manager. Use
|
// cache jar files in the standard file manager. Use
|
||||||
|
|
|
@ -307,7 +307,7 @@ public class Flags {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache of modifier sets.
|
// Cache of modifier sets.
|
||||||
private static Map<Long, Set<Modifier>> modifierSets =
|
private static final Map<Long, Set<Modifier>> modifierSets =
|
||||||
new java.util.concurrent.ConcurrentHashMap<Long, Set<Modifier>>(64);
|
new java.util.concurrent.ConcurrentHashMap<Long, Set<Modifier>>(64);
|
||||||
|
|
||||||
public static boolean isStatic(Symbol symbol) {
|
public static boolean isStatic(Symbol symbol) {
|
||||||
|
@ -356,7 +356,7 @@ public class Flags {
|
||||||
VARARGS("varargs"),
|
VARARGS("varargs"),
|
||||||
PACKAGE("package");
|
PACKAGE("package");
|
||||||
|
|
||||||
String name;
|
private final String name;
|
||||||
|
|
||||||
Flag(String name) {
|
Flag(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
|
@ -110,7 +110,7 @@ public class Kinds {
|
||||||
INSTANCE_INIT("kindname.instance.init"),
|
INSTANCE_INIT("kindname.instance.init"),
|
||||||
PACKAGE("kindname.package");
|
PACKAGE("kindname.package");
|
||||||
|
|
||||||
private String name;
|
private final String name;
|
||||||
|
|
||||||
KindName(String name) {
|
KindName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
|
@ -28,11 +28,14 @@ package com.sun.tools.javac.code;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
import com.sun.tools.javac.code.Symbol.*;
|
import com.sun.tools.javac.code.Symbol.*;
|
||||||
import com.sun.tools.javac.util.Context;
|
import com.sun.tools.javac.util.Context;
|
||||||
import com.sun.tools.javac.util.List;
|
import com.sun.tools.javac.util.List;
|
||||||
import com.sun.tools.javac.util.Options;
|
import com.sun.tools.javac.util.Options;
|
||||||
import com.sun.tools.javac.util.Pair;
|
import com.sun.tools.javac.util.Pair;
|
||||||
|
|
||||||
import static com.sun.tools.javac.code.Flags.*;
|
import static com.sun.tools.javac.code.Flags.*;
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,7 +98,8 @@ public class Lint
|
||||||
private final EnumSet<LintCategory> values;
|
private final EnumSet<LintCategory> values;
|
||||||
private final EnumSet<LintCategory> suppressedValues;
|
private final EnumSet<LintCategory> suppressedValues;
|
||||||
|
|
||||||
private static Map<String, LintCategory> map = new HashMap<String,LintCategory>();
|
private static final Map<String, LintCategory> map =
|
||||||
|
new java.util.concurrent.ConcurrentHashMap<String, LintCategory>(20);
|
||||||
|
|
||||||
|
|
||||||
protected Lint(Context context) {
|
protected Lint(Context context) {
|
||||||
|
|
|
@ -87,7 +87,7 @@ public enum Source {
|
||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
private static Map<String,Source> tab = new HashMap<String,Source>();
|
private static final Map<String,Source> tab = new HashMap<String,Source>();
|
||||||
static {
|
static {
|
||||||
for (Source s : values()) {
|
for (Source s : values()) {
|
||||||
tab.put(s.name, s);
|
tab.put(s.name, s);
|
||||||
|
|
|
@ -166,7 +166,7 @@ public enum TargetType {
|
||||||
static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22;
|
static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22;
|
||||||
|
|
||||||
private final int targetTypeValue;
|
private final int targetTypeValue;
|
||||||
private Set<TargetAttribute> flags;
|
private final Set<TargetAttribute> flags;
|
||||||
|
|
||||||
TargetType(int targetTypeValue, TargetAttribute... attributes) {
|
TargetType(int targetTypeValue, TargetAttribute... attributes) {
|
||||||
if (targetTypeValue < Byte.MIN_VALUE
|
if (targetTypeValue < Byte.MIN_VALUE
|
||||||
|
@ -233,10 +233,10 @@ public enum TargetType {
|
||||||
return this.targetTypeValue;
|
return this.targetTypeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TargetType[] targets = null;
|
private static final TargetType[] targets;
|
||||||
|
|
||||||
private static TargetType[] buildTargets() {
|
static {
|
||||||
TargetType[] targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
|
targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
|
||||||
TargetType[] alltargets = values();
|
TargetType[] alltargets = values();
|
||||||
for (TargetType target : alltargets) {
|
for (TargetType target : alltargets) {
|
||||||
if (target.targetTypeValue >= 0)
|
if (target.targetTypeValue >= 0)
|
||||||
|
@ -246,13 +246,9 @@ public enum TargetType {
|
||||||
if (targets[i] == null)
|
if (targets[i] == null)
|
||||||
targets[i] = UNKNOWN;
|
targets[i] = UNKNOWN;
|
||||||
}
|
}
|
||||||
return targets;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isValidTargetTypeValue(int tag) {
|
public static boolean isValidTargetTypeValue(int tag) {
|
||||||
if (targets == null)
|
|
||||||
targets = buildTargets();
|
|
||||||
|
|
||||||
if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
|
if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -260,9 +256,6 @@ public enum TargetType {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TargetType fromTargetTypeValue(int tag) {
|
public static TargetType fromTargetTypeValue(int tag) {
|
||||||
if (targets == null)
|
|
||||||
targets = buildTargets();
|
|
||||||
|
|
||||||
if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
|
if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
|
|
||||||
|
|
|
@ -135,9 +135,11 @@ public enum TypeTag {
|
||||||
/** This field will only be used for tags related with numeric types for
|
/** This field will only be used for tags related with numeric types for
|
||||||
* optimization reasons.
|
* optimization reasons.
|
||||||
*/
|
*/
|
||||||
private int order = 0;
|
private final int order;
|
||||||
|
|
||||||
private TypeTag() {}
|
private TypeTag() {
|
||||||
|
this(0);
|
||||||
|
}
|
||||||
|
|
||||||
private TypeTag(int order) {
|
private TypeTag(int order) {
|
||||||
this.order = order;
|
this.order = order;
|
||||||
|
|
|
@ -2849,7 +2849,7 @@ public class Types {
|
||||||
}
|
}
|
||||||
return tvars1;
|
return tvars1;
|
||||||
}
|
}
|
||||||
static private Mapping newInstanceFun = new Mapping("newInstanceFun") {
|
private static final Mapping newInstanceFun = new Mapping("newInstanceFun") {
|
||||||
public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound()); }
|
public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound()); }
|
||||||
};
|
};
|
||||||
// </editor-fold>
|
// </editor-fold>
|
||||||
|
|
|
@ -62,9 +62,9 @@ strictfp class ConstFold {
|
||||||
syms = Symtab.instance(context);
|
syms = Symtab.instance(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Integer minusOne = -1;
|
static final Integer minusOne = -1;
|
||||||
static Integer zero = 0;
|
static final Integer zero = 0;
|
||||||
static Integer one = 1;
|
static final Integer one = 1;
|
||||||
|
|
||||||
/** Convert boolean to integer (true = 1, false = 0).
|
/** Convert boolean to integer (true = 1, false = 0).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -246,8 +246,8 @@ public class Flow {
|
||||||
*/
|
*/
|
||||||
SPECULATIVE_LOOP("var.might.be.assigned.in.loop", true);
|
SPECULATIVE_LOOP("var.might.be.assigned.in.loop", true);
|
||||||
|
|
||||||
String errKey;
|
final String errKey;
|
||||||
boolean isFinal;
|
final boolean isFinal;
|
||||||
|
|
||||||
FlowKind(String errKey, boolean isFinal) {
|
FlowKind(String errKey, boolean isFinal) {
|
||||||
this.errKey = errKey;
|
this.errKey = errKey;
|
||||||
|
@ -295,7 +295,7 @@ public class Flow {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
JCTree.Tag treeTag;
|
final JCTree.Tag treeTag;
|
||||||
|
|
||||||
private JumpKind(Tag treeTag) {
|
private JumpKind(Tag treeTag) {
|
||||||
this.treeTag = treeTag;
|
this.treeTag = treeTag;
|
||||||
|
|
|
@ -156,7 +156,7 @@ public class Resolve {
|
||||||
OBJECT_INIT("object-init"),
|
OBJECT_INIT("object-init"),
|
||||||
INTERNAL("internal");
|
INTERNAL("internal");
|
||||||
|
|
||||||
String opt;
|
final String opt;
|
||||||
|
|
||||||
private VerboseResolutionMode(String opt) {
|
private VerboseResolutionMode(String opt) {
|
||||||
this.opt = opt;
|
this.opt = opt;
|
||||||
|
@ -3381,8 +3381,8 @@ public class Resolve {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
boolean isBoxingRequired;
|
final boolean isBoxingRequired;
|
||||||
boolean isVarargsRequired;
|
final boolean isVarargsRequired;
|
||||||
|
|
||||||
MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) {
|
MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) {
|
||||||
this.isBoxingRequired = isBoxingRequired;
|
this.isBoxingRequired = isBoxingRequired;
|
||||||
|
|
|
@ -83,7 +83,7 @@ public class ZipFileIndex {
|
||||||
public final static long NOT_MODIFIED = Long.MIN_VALUE;
|
public final static long NOT_MODIFIED = Long.MIN_VALUE;
|
||||||
|
|
||||||
|
|
||||||
private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
|
private static final boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
|
||||||
|
|
||||||
private Map<RelativeDirectory, DirectoryEntry> directories =
|
private Map<RelativeDirectory, DirectoryEntry> directories =
|
||||||
Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
|
Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
|
||||||
|
|
|
@ -1825,7 +1825,7 @@ public class Code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Type jsrReturnValue = new Type(INT, null);
|
static final Type jsrReturnValue = new Type(INT, null);
|
||||||
|
|
||||||
|
|
||||||
/* **************************************************************************
|
/* **************************************************************************
|
||||||
|
|
|
@ -86,17 +86,15 @@ public enum Target {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Target MIN;
|
private static final Target MIN = values()[0];
|
||||||
public static Target MIN() { return MIN; }
|
public static Target MIN() { return MIN; }
|
||||||
|
|
||||||
private static Target MAX;
|
private static final Target MAX = values()[values().length - 1];
|
||||||
public static Target MAX() { return MAX; }
|
public static Target MAX() { return MAX; }
|
||||||
|
|
||||||
private static Map<String,Target> tab = new HashMap<String,Target>();
|
private static final Map<String,Target> tab = new HashMap<String,Target>();
|
||||||
static {
|
static {
|
||||||
for (Target t : values()) {
|
for (Target t : values()) {
|
||||||
if (MIN == null) MIN = t;
|
|
||||||
MAX = t;
|
|
||||||
tab.put(t.name, t);
|
tab.put(t.name, t);
|
||||||
}
|
}
|
||||||
tab.put("5", JDK1_5);
|
tab.put("5", JDK1_5);
|
||||||
|
|
|
@ -189,7 +189,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CompilePolicy DEFAULT_COMPILE_POLICY = CompilePolicy.BY_TODO;
|
private static final CompilePolicy DEFAULT_COMPILE_POLICY = CompilePolicy.BY_TODO;
|
||||||
|
|
||||||
protected static enum ImplicitSourcePolicy {
|
protected static enum ImplicitSourcePolicy {
|
||||||
/** Don't generate or process implicitly read source files. */
|
/** Don't generate or process implicitly read source files. */
|
||||||
|
@ -543,7 +543,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
|
||||||
public static CompileState max(CompileState a, CompileState b) {
|
public static CompileState max(CompileState a, CompileState b) {
|
||||||
return a.value > b.value ? a : b;
|
return a.value > b.value ? a : b;
|
||||||
}
|
}
|
||||||
private int value;
|
private final int value;
|
||||||
};
|
};
|
||||||
/** Partial map to record which compiler phases have been executed
|
/** Partial map to record which compiler phases have been executed
|
||||||
* for each compilation unit. Used for ATTR and FLOW phases.
|
* for each compilation unit. Used for ATTR and FLOW phases.
|
||||||
|
|
|
@ -167,7 +167,6 @@ public enum Option {
|
||||||
ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) {
|
ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) {
|
||||||
@Override
|
@Override
|
||||||
public boolean process(OptionHelper helper, String option, String operand) {
|
public boolean process(OptionHelper helper, String option, String operand) {
|
||||||
// System.err.println("process encoding " + operand);
|
|
||||||
return super.process(helper, option, operand);
|
return super.process(helper, option, operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,9 +245,7 @@ public enum Option {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
A("-A", "opt.arg.key.equals.value", "opt.A", STANDARD, BASIC) {
|
A("-A", "opt.arg.key.equals.value", "opt.A", STANDARD, BASIC, true) {
|
||||||
{ hasSuffix = true; }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(String arg) {
|
public boolean matches(String arg) {
|
||||||
return arg.startsWith("-A");
|
return arg.startsWith("-A");
|
||||||
|
@ -293,8 +290,6 @@ public enum Option {
|
||||||
// This option exists only for the purpose of documenting itself.
|
// This option exists only for the purpose of documenting itself.
|
||||||
// It's actually implemented by the launcher.
|
// It's actually implemented by the launcher.
|
||||||
J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO) {
|
J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO) {
|
||||||
{ hasSuffix = true; }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(OptionHelper helper, String option) {
|
public boolean process(OptionHelper helper, String option) {
|
||||||
throw new AssertionError
|
throw new AssertionError
|
||||||
|
@ -302,10 +297,6 @@ public enum Option {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// stop after parsing and attributing.
|
|
||||||
// new HiddenOption("-attrparseonly"),
|
|
||||||
|
|
||||||
// new Option("-moreinfo", "opt.moreinfo") {
|
|
||||||
MOREINFO("-moreinfo", null, HIDDEN, BASIC) {
|
MOREINFO("-moreinfo", null, HIDDEN, BASIC) {
|
||||||
@Override
|
@Override
|
||||||
public boolean process(OptionHelper helper, String option) {
|
public boolean process(OptionHelper helper, String option) {
|
||||||
|
@ -317,23 +308,6 @@ public enum Option {
|
||||||
// treat warnings as errors
|
// treat warnings as errors
|
||||||
WERROR("-Werror", "opt.Werror", STANDARD, BASIC),
|
WERROR("-Werror", "opt.Werror", STANDARD, BASIC),
|
||||||
|
|
||||||
// // use complex inference from context in the position of a method call argument
|
|
||||||
// COMPLEXINFERENCE("-complexinference", null, HIDDEN, BASIC),
|
|
||||||
|
|
||||||
// generare source stubs
|
|
||||||
// new HiddenOption("-stubs"),
|
|
||||||
|
|
||||||
// relax some constraints to allow compiling from stubs
|
|
||||||
// new HiddenOption("-relax"),
|
|
||||||
|
|
||||||
// output source after translating away inner classes
|
|
||||||
// new Option("-printflat", "opt.printflat"),
|
|
||||||
// new HiddenOption("-printflat"),
|
|
||||||
|
|
||||||
// display scope search details
|
|
||||||
// new Option("-printsearch", "opt.printsearch"),
|
|
||||||
// new HiddenOption("-printsearch"),
|
|
||||||
|
|
||||||
// prompt after each error
|
// prompt after each error
|
||||||
// new Option("-prompt", "opt.prompt"),
|
// new Option("-prompt", "opt.prompt"),
|
||||||
PROMPT("-prompt", null, HIDDEN, BASIC),
|
PROMPT("-prompt", null, HIDDEN, BASIC),
|
||||||
|
@ -342,13 +316,8 @@ public enum Option {
|
||||||
DOE("-doe", null, HIDDEN, BASIC),
|
DOE("-doe", null, HIDDEN, BASIC),
|
||||||
|
|
||||||
// output source after type erasure
|
// output source after type erasure
|
||||||
// new Option("-s", "opt.s"),
|
|
||||||
PRINTSOURCE("-printsource", null, HIDDEN, BASIC),
|
PRINTSOURCE("-printsource", null, HIDDEN, BASIC),
|
||||||
|
|
||||||
// output shrouded class files
|
|
||||||
// new Option("-scramble", "opt.scramble"),
|
|
||||||
// new Option("-scrambleall", "opt.scrambleall"),
|
|
||||||
|
|
||||||
// display warnings for generic unchecked operations
|
// display warnings for generic unchecked operations
|
||||||
WARNUNCHECKED("-warnunchecked", null, HIDDEN, BASIC) {
|
WARNUNCHECKED("-warnunchecked", null, HIDDEN, BASIC) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -408,18 +377,16 @@ public enum Option {
|
||||||
* -XDx sets the option x to the value x.
|
* -XDx sets the option x to the value x.
|
||||||
*/
|
*/
|
||||||
XD("-XD", null, HIDDEN, BASIC) {
|
XD("-XD", null, HIDDEN, BASIC) {
|
||||||
String s;
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(String s) {
|
public boolean matches(String s) {
|
||||||
this.s = s;
|
|
||||||
return s.startsWith(text);
|
return s.startsWith(text);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean process(OptionHelper helper, String option) {
|
public boolean process(OptionHelper helper, String option) {
|
||||||
s = s.substring(text.length());
|
option = option.substring(text.length());
|
||||||
int eq = s.indexOf('=');
|
int eq = option.indexOf('=');
|
||||||
String key = (eq < 0) ? s : s.substring(0, eq);
|
String key = (eq < 0) ? option : option.substring(0, eq);
|
||||||
String value = (eq < 0) ? s : s.substring(eq+1);
|
String value = (eq < 0) ? option : option.substring(eq+1);
|
||||||
helper.put(key, value);
|
helper.put(key, value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -428,8 +395,6 @@ public enum Option {
|
||||||
// This option exists only for the purpose of documenting itself.
|
// This option exists only for the purpose of documenting itself.
|
||||||
// It's actually implemented by the CommandLine class.
|
// It's actually implemented by the CommandLine class.
|
||||||
AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO) {
|
AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO) {
|
||||||
{ hasSuffix = true; }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(OptionHelper helper, String option) {
|
public boolean process(OptionHelper helper, String option) {
|
||||||
throw new AssertionError("the @ flag should be caught by CommandLine.");
|
throw new AssertionError("the @ flag should be caught by CommandLine.");
|
||||||
|
@ -445,17 +410,15 @@ public enum Option {
|
||||||
* name to a separate list.
|
* name to a separate list.
|
||||||
*/
|
*/
|
||||||
SOURCEFILE("sourcefile", null, HIDDEN, INFO) {
|
SOURCEFILE("sourcefile", null, HIDDEN, INFO) {
|
||||||
String s;
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(String s) {
|
public boolean matches(String s) {
|
||||||
this.s = s;
|
|
||||||
return s.endsWith(".java") // Java source file
|
return s.endsWith(".java") // Java source file
|
||||||
|| SourceVersion.isName(s); // Legal type name
|
|| SourceVersion.isName(s); // Legal type name
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean process(OptionHelper helper, String option) {
|
public boolean process(OptionHelper helper, String option) {
|
||||||
if (s.endsWith(".java") ) {
|
if (option.endsWith(".java") ) {
|
||||||
File f = new File(s);
|
File f = new File(option);
|
||||||
if (!f.exists()) {
|
if (!f.exists()) {
|
||||||
helper.error("err.file.not.found", f);
|
helper.error("err.file.not.found", f);
|
||||||
return true;
|
return true;
|
||||||
|
@ -465,9 +428,9 @@ public enum Option {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
helper.addFile(f);
|
helper.addFile(f);
|
||||||
|
} else {
|
||||||
|
helper.addClassName(option);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
helper.addClassName(s);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -521,7 +484,7 @@ public enum Option {
|
||||||
|
|
||||||
/** Suffix option (-foo=bar or -foo:bar)
|
/** Suffix option (-foo=bar or -foo:bar)
|
||||||
*/
|
*/
|
||||||
boolean hasSuffix;
|
final boolean hasSuffix;
|
||||||
|
|
||||||
/** The kind of choices for this option, if any.
|
/** The kind of choices for this option, if any.
|
||||||
*/
|
*/
|
||||||
|
@ -535,24 +498,30 @@ public enum Option {
|
||||||
|
|
||||||
Option(String text, String descrKey,
|
Option(String text, String descrKey,
|
||||||
OptionKind kind, OptionGroup group) {
|
OptionKind kind, OptionGroup group) {
|
||||||
this(text, null, descrKey, kind, group, null, null);
|
this(text, null, descrKey, kind, group, null, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Option(String text, String argsNameKey, String descrKey,
|
Option(String text, String argsNameKey, String descrKey,
|
||||||
OptionKind kind, OptionGroup group) {
|
OptionKind kind, OptionGroup group) {
|
||||||
this(text, argsNameKey, descrKey, kind, group, null, null);
|
this(text, argsNameKey, descrKey, kind, group, null, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Option(String text, String argsNameKey, String descrKey,
|
||||||
|
OptionKind kind, OptionGroup group, boolean doHasSuffix) {
|
||||||
|
this(text, argsNameKey, descrKey, kind, group, null, null, doHasSuffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
Option(String text, String descrKey,
|
Option(String text, String descrKey,
|
||||||
OptionKind kind, OptionGroup group,
|
OptionKind kind, OptionGroup group,
|
||||||
ChoiceKind choiceKind, Map<String,Boolean> choices) {
|
ChoiceKind choiceKind, Map<String,Boolean> choices) {
|
||||||
this(text, null, descrKey, kind, group, choiceKind, choices);
|
this(text, null, descrKey, kind, group, choiceKind, choices, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Option(String text, String descrKey,
|
Option(String text, String descrKey,
|
||||||
OptionKind kind, OptionGroup group,
|
OptionKind kind, OptionGroup group,
|
||||||
ChoiceKind choiceKind, String... choices) {
|
ChoiceKind choiceKind, String... choices) {
|
||||||
this(text, null, descrKey, kind, group, choiceKind, createChoices(choices));
|
this(text, null, descrKey, kind, group, choiceKind,
|
||||||
|
createChoices(choices), false);
|
||||||
}
|
}
|
||||||
// where
|
// where
|
||||||
private static Map<String,Boolean> createChoices(String... choices) {
|
private static Map<String,Boolean> createChoices(String... choices) {
|
||||||
|
@ -564,7 +533,8 @@ public enum Option {
|
||||||
|
|
||||||
private Option(String text, String argsNameKey, String descrKey,
|
private Option(String text, String argsNameKey, String descrKey,
|
||||||
OptionKind kind, OptionGroup group,
|
OptionKind kind, OptionGroup group,
|
||||||
ChoiceKind choiceKind, Map<String,Boolean> choices) {
|
ChoiceKind choiceKind, Map<String,Boolean> choices,
|
||||||
|
boolean doHasSuffix) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.argsNameKey = argsNameKey;
|
this.argsNameKey = argsNameKey;
|
||||||
this.descrKey = descrKey;
|
this.descrKey = descrKey;
|
||||||
|
@ -573,7 +543,7 @@ public enum Option {
|
||||||
this.choiceKind = choiceKind;
|
this.choiceKind = choiceKind;
|
||||||
this.choices = choices;
|
this.choices = choices;
|
||||||
char lastChar = text.charAt(text.length()-1);
|
char lastChar = text.charAt(text.length()-1);
|
||||||
hasSuffix = lastChar == ':' || lastChar == '=';
|
this.hasSuffix = doHasSuffix || lastChar == ':' || lastChar == '=';
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getText() {
|
public String getText() {
|
||||||
|
|
|
@ -44,7 +44,7 @@ import static com.sun.tools.javac.util.LayoutCharacters.*;
|
||||||
*/
|
*/
|
||||||
public class JavaTokenizer {
|
public class JavaTokenizer {
|
||||||
|
|
||||||
private static boolean scannerDebug = false;
|
private static final boolean scannerDebug = false;
|
||||||
|
|
||||||
/** Allow hex floating-point literals.
|
/** Allow hex floating-point literals.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1336,7 +1336,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TreeScanner treeCleaner = new TreeScanner() {
|
private static final TreeScanner treeCleaner = new TreeScanner() {
|
||||||
public void scan(JCTree node) {
|
public void scan(JCTree node) {
|
||||||
super.scan(node);
|
super.scan(node);
|
||||||
if (node != null)
|
if (node != null)
|
||||||
|
|
|
@ -340,15 +340,17 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||||
*/
|
*/
|
||||||
LETEXPR; // ala scheme
|
LETEXPR; // ala scheme
|
||||||
|
|
||||||
private Tag noAssignTag;
|
private final Tag noAssignTag;
|
||||||
|
|
||||||
private static int numberOfOperators = MOD.ordinal() - POS.ordinal() + 1;
|
private static final int numberOfOperators = MOD.ordinal() - POS.ordinal() + 1;
|
||||||
|
|
||||||
private Tag(Tag noAssignTag) {
|
private Tag(Tag noAssignTag) {
|
||||||
this.noAssignTag = noAssignTag;
|
this.noAssignTag = noAssignTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tag() { }
|
private Tag() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
public static int getNumberOfOperators() {
|
public static int getNumberOfOperators() {
|
||||||
return numberOfOperators;
|
return numberOfOperators;
|
||||||
|
@ -1838,8 +1840,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||||
/** Toplevel # new */
|
/** Toplevel # new */
|
||||||
TOPLEVEL(ReferenceMode.NEW, false);
|
TOPLEVEL(ReferenceMode.NEW, false);
|
||||||
|
|
||||||
ReferenceMode mode;
|
final ReferenceMode mode;
|
||||||
boolean unbound;
|
final boolean unbound;
|
||||||
|
|
||||||
private ReferenceKind(ReferenceMode mode, boolean unbound) {
|
private ReferenceKind(ReferenceMode mode, boolean unbound) {
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -181,7 +181,7 @@ public abstract class BaseFileManager {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// where
|
// where
|
||||||
private static Set<Option> javacFileManagerOptions =
|
private static final Set<Option> javacFileManagerOptions =
|
||||||
Option.getJavacFileManagerOptions();
|
Option.getJavacFileManagerOptions();
|
||||||
|
|
||||||
public int isSupportedOption(String option) {
|
public int isSupportedOption(String option) {
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class List<A> extends AbstractCollection<A> implements java.util.List<A>
|
||||||
return (List<A>)EMPTY_LIST;
|
return (List<A>)EMPTY_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<?> EMPTY_LIST = new List<Object>(null,null) {
|
private static final List<?> EMPTY_LIST = new List<Object>(null,null) {
|
||||||
public List<Object> setTail(List<Object> tail) {
|
public List<Object> setTail(List<Object> tail) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ public class List<A> extends AbstractCollection<A> implements java.util.List<A>
|
||||||
return (List<T>)list;
|
return (List<T>)list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Iterator<?> EMPTYITERATOR = new Iterator<Object>() {
|
private static final Iterator<?> EMPTYITERATOR = new Iterator<Object>() {
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -91,7 +91,7 @@ public class MandatoryWarningHandler {
|
||||||
DeferredDiagnosticKind(String v) { value = v; }
|
DeferredDiagnosticKind(String v) { value = v; }
|
||||||
String getKey(String prefix) { return prefix + value; }
|
String getKey(String prefix) { return prefix + value; }
|
||||||
|
|
||||||
private String value;
|
private final String value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -249,7 +249,7 @@ public class RichDiagnosticFormatter extends
|
||||||
INTERSECTION("where.description.intersection");
|
INTERSECTION("where.description.intersection");
|
||||||
|
|
||||||
/** resource key for this where clause kind */
|
/** resource key for this where clause kind */
|
||||||
private String key;
|
private final String key;
|
||||||
|
|
||||||
WhereClauseKind(String key) {
|
WhereClauseKind(String key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
|
|
|
@ -147,7 +147,7 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Option[] recognizedOptions = {
|
static final Option[] recognizedOptions = {
|
||||||
new Option(true, "-o") {
|
new Option(true, "-o") {
|
||||||
void process(JavahTask task, String opt, String arg) {
|
void process(JavahTask task, String opt, String arg) {
|
||||||
task.ofile = new File(arg);
|
task.ofile = new File(arg);
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
|
||||||
final String[] aliases;
|
final String[] aliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Option[] recognizedOptions = {
|
static final Option[] recognizedOptions = {
|
||||||
|
|
||||||
new Option(false, "-help", "--help", "-?") {
|
new Option(false, "-help", "--help", "-?") {
|
||||||
void process(JavapTask task, String opt, String arg) {
|
void process(JavapTask task, String opt, String arg) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -61,16 +61,10 @@ public enum Modifier {
|
||||||
/** The modifier {@code native} */ NATIVE,
|
/** The modifier {@code native} */ NATIVE,
|
||||||
/** The modifier {@code strictfp} */ STRICTFP;
|
/** The modifier {@code strictfp} */ STRICTFP;
|
||||||
|
|
||||||
|
|
||||||
private String lowercase = null; // modifier name in lowercase
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns this modifier's name in lowercase.
|
* Returns this modifier's name in lowercase.
|
||||||
*/
|
*/
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (lowercase == null) {
|
return name().toLowerCase(java.util.Locale.US);
|
||||||
lowercase = name().toLowerCase(java.util.Locale.US);
|
|
||||||
}
|
|
||||||
return lowercase;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,19 +66,19 @@ import javax.lang.model.element.*;
|
||||||
public class ElementFilter {
|
public class ElementFilter {
|
||||||
private ElementFilter() {} // Do not instantiate.
|
private ElementFilter() {} // Do not instantiate.
|
||||||
|
|
||||||
private static Set<ElementKind> CONSTRUCTOR_KIND =
|
private static final Set<ElementKind> CONSTRUCTOR_KIND =
|
||||||
Collections.unmodifiableSet(EnumSet.of(ElementKind.CONSTRUCTOR));
|
Collections.unmodifiableSet(EnumSet.of(ElementKind.CONSTRUCTOR));
|
||||||
|
|
||||||
private static Set<ElementKind> FIELD_KINDS =
|
private static final Set<ElementKind> FIELD_KINDS =
|
||||||
Collections.unmodifiableSet(EnumSet.of(ElementKind.FIELD,
|
Collections.unmodifiableSet(EnumSet.of(ElementKind.FIELD,
|
||||||
ElementKind.ENUM_CONSTANT));
|
ElementKind.ENUM_CONSTANT));
|
||||||
private static Set<ElementKind> METHOD_KIND =
|
private static final Set<ElementKind> METHOD_KIND =
|
||||||
Collections.unmodifiableSet(EnumSet.of(ElementKind.METHOD));
|
Collections.unmodifiableSet(EnumSet.of(ElementKind.METHOD));
|
||||||
|
|
||||||
private static Set<ElementKind> PACKAGE_KIND =
|
private static final Set<ElementKind> PACKAGE_KIND =
|
||||||
Collections.unmodifiableSet(EnumSet.of(ElementKind.PACKAGE));
|
Collections.unmodifiableSet(EnumSet.of(ElementKind.PACKAGE));
|
||||||
|
|
||||||
private static Set<ElementKind> TYPE_KINDS =
|
private static final Set<ElementKind> TYPE_KINDS =
|
||||||
Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS,
|
Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS,
|
||||||
ElementKind.ENUM,
|
ElementKind.ENUM,
|
||||||
ElementKind.INTERFACE,
|
ElementKind.INTERFACE,
|
||||||
|
|
|
@ -97,7 +97,7 @@ public enum StandardLocation implements Location {
|
||||||
return locations.get(name);
|
return locations.get(name);
|
||||||
}
|
}
|
||||||
//where
|
//where
|
||||||
private static ConcurrentMap<String,Location> locations
|
private static final ConcurrentMap<String,Location> locations
|
||||||
= new ConcurrentHashMap<String,Location>();
|
= new ConcurrentHashMap<String,Location>();
|
||||||
|
|
||||||
public String getName() { return name(); }
|
public String getName() { return name(); }
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8003967
|
||||||
|
* @summary detect and remove all mutable implicit static enum fields in langtools
|
||||||
|
* @run main DetectMutableStaticFields
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.JavaFileManager;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import javax.tools.StandardJavaFileManager;
|
||||||
|
import javax.tools.StandardLocation;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
import com.sun.tools.classfile.ClassFile;
|
||||||
|
import com.sun.tools.classfile.ConstantPoolException;
|
||||||
|
import com.sun.tools.classfile.Descriptor;
|
||||||
|
import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
|
||||||
|
import com.sun.tools.classfile.Field;
|
||||||
|
|
||||||
|
import static javax.tools.JavaFileObject.Kind.CLASS;
|
||||||
|
import static com.sun.tools.classfile.AccessFlags.ACC_ENUM;
|
||||||
|
import static com.sun.tools.classfile.AccessFlags.ACC_FINAL;
|
||||||
|
import static com.sun.tools.classfile.AccessFlags.ACC_STATIC;
|
||||||
|
|
||||||
|
public class DetectMutableStaticFields {
|
||||||
|
|
||||||
|
private static final String keyResource =
|
||||||
|
"com/sun/tools/javac/tree/JCTree.class";
|
||||||
|
|
||||||
|
private String[] packagesToSeekFor = new String[] {
|
||||||
|
"javax.tools",
|
||||||
|
"javax.lang.model",
|
||||||
|
"com.sun.javadoc",
|
||||||
|
"com.sun.source",
|
||||||
|
"com.sun.tools.classfile",
|
||||||
|
"com.sun.tools.doclets",
|
||||||
|
"com.sun.tools.javac",
|
||||||
|
"com.sun.tools.javadoc",
|
||||||
|
"com.sun.tools.javah",
|
||||||
|
"com.sun.tools.javap",
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Map<String, List<String>> classFieldsToIgnoreMap = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("javax/tools/ToolProvider",
|
||||||
|
Arrays.asList("instance"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/javah/JavahTask",
|
||||||
|
Arrays.asList("versionRB"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/classfile/Dependencies$DefaultFilter",
|
||||||
|
Arrays.asList("instance"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/javap/JavapTask",
|
||||||
|
Arrays.asList("versionRB"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/doclets/formats/html/HtmlDoclet",
|
||||||
|
Arrays.asList("docletToStart"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/javac/util/JCDiagnostic",
|
||||||
|
Arrays.asList("fragmentFormatter"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/javac/util/JavacMessages",
|
||||||
|
Arrays.asList("defaultBundle", "defaultMessages"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/javac/file/ZipFileIndexCache",
|
||||||
|
Arrays.asList("sharedInstance"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/javac/main/JavaCompiler",
|
||||||
|
Arrays.asList("versionRB"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/javac/code/Type",
|
||||||
|
Arrays.asList("moreInfo"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/javac/util/SharedNameTable",
|
||||||
|
Arrays.asList("freelist"));
|
||||||
|
classFieldsToIgnoreMap.
|
||||||
|
put("com/sun/tools/javac/util/Log",
|
||||||
|
Arrays.asList("useRawMessages"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> errors = new ArrayList<>();
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
new DetectMutableStaticFields().run();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new AssertionError(
|
||||||
|
"Exception during test execution with cause ",
|
||||||
|
ex.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void run()
|
||||||
|
throws
|
||||||
|
IOException,
|
||||||
|
ConstantPoolException,
|
||||||
|
InvalidDescriptor,
|
||||||
|
URISyntaxException {
|
||||||
|
|
||||||
|
URI resource = findResource(keyResource);
|
||||||
|
if (resource == null) {
|
||||||
|
throw new AssertionError("Resource " + keyResource +
|
||||||
|
"not found in the class path");
|
||||||
|
}
|
||||||
|
analyzeResource(resource);
|
||||||
|
|
||||||
|
if (errors.size() > 0) {
|
||||||
|
for (String error: errors) {
|
||||||
|
System.err.println(error);
|
||||||
|
}
|
||||||
|
throw new AssertionError("There are mutable fields, "
|
||||||
|
+ "please check output");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
URI findResource(String className) throws URISyntaxException {
|
||||||
|
URI uri = getClass().getClassLoader().getResource(className).toURI();
|
||||||
|
if (uri.getScheme().equals("jar")) {
|
||||||
|
String ssp = uri.getRawSchemeSpecificPart();
|
||||||
|
int sep = ssp.lastIndexOf("!");
|
||||||
|
uri = new URI(ssp.substring(0, sep));
|
||||||
|
} else if (uri.getScheme().equals("file")) {
|
||||||
|
uri = new URI(uri.getPath().substring(0,
|
||||||
|
uri.getPath().length() - keyResource.length()));
|
||||||
|
}
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean shouldAnalyzePackage(String packageName) {
|
||||||
|
for (String aPackage: packagesToSeekFor) {
|
||||||
|
if (packageName.contains(aPackage)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void analyzeResource(URI resource)
|
||||||
|
throws
|
||||||
|
IOException,
|
||||||
|
ConstantPoolException,
|
||||||
|
InvalidDescriptor {
|
||||||
|
JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
|
||||||
|
StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
|
||||||
|
JavaFileManager.Location location =
|
||||||
|
StandardLocation.locationFor(resource.getPath());
|
||||||
|
fm.setLocation(location, com.sun.tools.javac.util.List.of(
|
||||||
|
new File(resource.getPath())));
|
||||||
|
|
||||||
|
for (JavaFileObject file : fm.list(location, "", EnumSet.of(CLASS), true)) {
|
||||||
|
String className = fm.inferBinaryName(location, file);
|
||||||
|
int index = className.lastIndexOf('.');
|
||||||
|
String pckName = index == -1 ? "" : className.substring(0, index);
|
||||||
|
if (shouldAnalyzePackage(pckName)) {
|
||||||
|
analyzeClassFile(ClassFile.read(file.openInputStream()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> currentFieldsToIgnore;
|
||||||
|
|
||||||
|
boolean ignoreField(String field) {
|
||||||
|
if (currentFieldsToIgnore != null) {
|
||||||
|
for (String fieldToIgnore : currentFieldsToIgnore) {
|
||||||
|
if (field.equals(fieldToIgnore)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void analyzeClassFile(ClassFile classFileToCheck)
|
||||||
|
throws
|
||||||
|
IOException,
|
||||||
|
ConstantPoolException,
|
||||||
|
Descriptor.InvalidDescriptor {
|
||||||
|
boolean enumClass =
|
||||||
|
(classFileToCheck.access_flags.flags & ACC_ENUM) != 0;
|
||||||
|
boolean nonFinalStaticEnumField;
|
||||||
|
boolean nonFinalStaticField;
|
||||||
|
|
||||||
|
currentFieldsToIgnore =
|
||||||
|
classFieldsToIgnoreMap.get(classFileToCheck.getName());
|
||||||
|
|
||||||
|
for (Field field : classFileToCheck.fields) {
|
||||||
|
if (ignoreField(field.getName(classFileToCheck.constant_pool))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nonFinalStaticEnumField =
|
||||||
|
(field.access_flags.flags & (ACC_ENUM | ACC_FINAL)) == 0;
|
||||||
|
nonFinalStaticField =
|
||||||
|
(field.access_flags.flags & ACC_STATIC) != 0 &&
|
||||||
|
(field.access_flags.flags & ACC_FINAL) == 0;
|
||||||
|
if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) {
|
||||||
|
errors.add("There is a mutable field named " +
|
||||||
|
field.getName(classFileToCheck.constant_pool) +
|
||||||
|
", at class " +
|
||||||
|
classFileToCheck.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue