	public boolean match(String command) {
		if(cleft == null){
			//The compilation error happened during the signature declaration, so
			//we can't match it, nor can we even tell if it's what they intended for us to run.
			return false;
		}
		boolean case_sensitive = Prefs.CaseSensitive();
		String[] cmds = command.split(" ");
		List<String> args = new ArrayList<>(Arrays.asList(cmds));
		boolean isAMatch = true;
		StringBuilder lastVar = new StringBuilder();
		int lastJ = 0;
		for(int j = 0; j < cleft.size(); j++) {
			if(!isAMatch) {
				break;
			}
			lastJ = j;
			Construct c = cleft.get(j);
			if(args.size() <= j) {
				if(c.getCType() != ConstructType.VARIABLE || !((Variable) c).isOptional()) {
					isAMatch = false;
				}
				break;
			}
			String arg = args.get(j);
			if(c.getCType() != ConstructType.VARIABLE) {
				if(case_sensitive && !c.val().equals(arg) || !case_sensitive && !c.val().equalsIgnoreCase(arg)) {
					isAMatch = false;
					continue;
				}
			} else {
				//It's a variable. If it's optional, the rest of them are optional too, so as long as the size of
				//args isn't greater than the size of cleft, it's a match
				if(((Variable) c).isOptional()) {
					if(args.size() <= cleft.size()) {
						return true;
					} else {
						Construct fin = cleft.get(cleft.size() - 1);
						if(fin instanceof Variable) {
							if(((Variable) fin).isFinal()) {
								return true;
							}
						}
						return false;
					}
				}
			}
			if(j == cleft.size() - 1) {
				if(cleft.get(j).getCType() == ConstructType.VARIABLE) {
					Variable lv = (Variable) cleft.get(j);
					if(lv.isFinal()) {
						for(int a = j; a < args.size(); a++) {
							if(lastVar.length() == 0) {
								lastVar.append(args.get(a));
							} else {
								lastVar.append(" ").append(args.get(a));
							}
						}
					}
				}
			}
		}
		boolean lastIsFinal = false;
		if(cleft.get(cleft.size() - 1) instanceof Variable) {
			Variable v = (Variable) cleft.get(cleft.size() - 1);
			if(v.isFinal()) {
				lastIsFinal = true;
			}
		}
		if((cleft.get(lastJ) instanceof Variable && ((Variable) cleft.get(lastJ)).isOptional())) {
			return true;
		}

		if(cleft.size() != cmds.length && !lastIsFinal) {
			isAMatch = false;
		}
		return isAMatch;
	}

	public boolean match(String command) {
		if(cleft == null){
			//The compilation error happened during the signature declaration, so
			//we can't match it, nor can we even tell if it's what they intended for us to run.
			return false;
		}
		boolean case_sensitive = Prefs.CaseSensitive();
		String[] cmds = command.split(" ");
		List<String> args = new ArrayList<String>(Arrays.asList(cmds));
		boolean isAMatch = true;
		StringBuilder lastVar = new StringBuilder();
		int lastJ = 0;
		for(int j = 0; j < cleft.size(); j++) {
			if(!isAMatch) {
				break;
			}
			lastJ = j;
			Construct c = cleft.get(j);
			if(args.size() <= j) {
				if(c.getCType() != ConstructType.VARIABLE || !((Variable) c).isOptional()) {
					isAMatch = false;
				}
				break;
			}
			String arg = args.get(j);
			if(c.getCType() != ConstructType.VARIABLE) {
				if(case_sensitive && !c.val().equals(arg) || !case_sensitive && !c.val().equalsIgnoreCase(arg)) {
					isAMatch = false;
					continue;
				}
			} else {
				//It's a variable. If it's optional, the rest of them are optional too, so as long as the size of
				//args isn't greater than the size of cleft, it's a match
				if(((Variable) c).isOptional()) {
					if(args.size() <= cleft.size()) {
						return true;
					} else {
						Construct fin = cleft.get(cleft.size() - 1);
						if(fin instanceof Variable) {
							if(((Variable) fin).isFinal()) {
								return true;
							}
						}
						return false;
					}
				}
			}
			if(j == cleft.size() - 1) {
				if(cleft.get(j).getCType() == ConstructType.VARIABLE) {
					Variable lv = (Variable) cleft.get(j);
					if(lv.isFinal()) {
						for(int a = j; a < args.size(); a++) {
							if(lastVar.length() == 0) {
								lastVar.append(args.get(a));
							} else {
								lastVar.append(" ").append(args.get(a));
							}
						}
					}
				}
			}
		}
		boolean lastIsFinal = false;
		if(cleft.get(cleft.size() - 1) instanceof Variable) {
			Variable v = (Variable) cleft.get(cleft.size() - 1);
			if(v.isFinal()) {
				lastIsFinal = true;
			}
		}
		if((cleft.get(lastJ) instanceof Variable && ((Variable) cleft.get(lastJ)).isOptional())) {
			return true;
		}

		if(cleft.size() != cmds.length && !lastIsFinal) {
			isAMatch = false;
		}
		return isAMatch;
	}

Replace Generic With Diamond ArrayList<String> with ArrayList<> in method public match(command String) : boolean from class com.laytonsmith.core.Script


	public List<Variable> getVariables(String command) {
		String[] cmds = command.split(" ");
		List<String> args = new ArrayList<>(Arrays.asList(cmds));

		StringBuilder lastVar = new StringBuilder();

		ArrayList<Variable> vars = new ArrayList<>();
		Variable v = null;
		for(int j = 0; j < cleft.size(); j++) {
			try {
				if(cleft.get(j).getCType() == ConstructType.VARIABLE) {
					if(((Variable) cleft.get(j)).getVariableName().equals("$")) {
						for(int k = j; k < args.size(); k++) {
							lastVar.append(args.get(k).trim()).append(" ");
						}
						v = new Variable(((Variable) cleft.get(j)).getVariableName(),
								lastVar.toString().trim(), Target.UNKNOWN);
					} else {
						v = new Variable(((Variable) cleft.get(j)).getVariableName(),
								args.get(j), Target.UNKNOWN);
					}
				}
			} catch (IndexOutOfBoundsException e) {
				v = new Variable(((Variable) cleft.get(j)).getVariableName(),
						((Variable) cleft.get(j)).getDefault(), Target.UNKNOWN);
			}
			if(v != null) {
				vars.add(v);
			}
		}
		return vars;
	}

	public List<Variable> getVariables(String command) {
		String[] cmds = command.split(" ");
		List<String> args = new ArrayList<String>(Arrays.asList(cmds));

		StringBuilder lastVar = new StringBuilder();

		ArrayList<Variable> vars = new ArrayList<>();
		Variable v = null;
		for(int j = 0; j < cleft.size(); j++) {
			try {
				if(cleft.get(j).getCType() == ConstructType.VARIABLE) {
					if(((Variable) cleft.get(j)).getVariableName().equals("$")) {
						for(int k = j; k < args.size(); k++) {
							lastVar.append(args.get(k).trim()).append(" ");
						}
						v = new Variable(((Variable) cleft.get(j)).getVariableName(),
								lastVar.toString().trim(), Target.UNKNOWN);
					} else {
						v = new Variable(((Variable) cleft.get(j)).getVariableName(),
								args.get(j), Target.UNKNOWN);
					}
				}
			} catch (IndexOutOfBoundsException e) {
				v = new Variable(((Variable) cleft.get(j)).getVariableName(),
						((Variable) cleft.get(j)).getDefault(), Target.UNKNOWN);
			}
			if(v != null) {
				vars.add(v);
			}
		}
		return vars;
	}

Replace Generic With Diamond ArrayList<String> with ArrayList<> in method public getVariables(command String) : List<Variable> from class com.laytonsmith.core.Script


	@Override
	public Set<String> getEntries() {
		Set<String> ret = new HashSet<>();
		try {
			for(String e : t.getEntries()) {
				ret.add(e);
			}
		} catch(NoSuchMethodError ex){
			// Probably 1.8.5 or prior
			for(OfflinePlayer o : (Set<OfflinePlayer>) ReflectionUtils.invokeMethod(t, "getPlayers")) {
				ret.add(o.getName());
			}
		}
		return ret;
	}

	@Override
	public Set<String> getEntries() {
		Set<String> ret = new HashSet<String>();
		try {
			for(String e : t.getEntries()) {
				ret.add(e);
			}
		} catch(NoSuchMethodError ex){
			// Probably 1.8.5 or prior
			for(OfflinePlayer o : (Set<OfflinePlayer>) ReflectionUtils.invokeMethod(t, "getPlayers")) {
				ret.add(o.getName());
			}
		}
		return ret;
	}

Replace Generic With Diamond HashSet<String> with HashSet<> in method public getEntries() : Set<String> from class com.laytonsmith.abstraction.bukkit.BukkitMCTeam


		@Override
		public CArray exec(final Target t, final Environment environment, Construct... args) throws ConfigRuntimeException {
			CArray array = Static.getArray(args[0], t);
			boolean compareTypes = true;
			if(args.length == 2) {
				compareTypes = Static.getBoolean(args[1]);
			}
			final boolean fCompareTypes = compareTypes;
			if(array.inAssociativeMode()) {
				return array.clone();
			} else {
				List<Construct> asList = array.asList();
				CArray newArray = new CArray(t);
				Set<Construct> set = new LinkedComparatorSet<>(asList, new LinkedComparatorSet.EqualsComparator<Construct>() {

					@Override
					public boolean checkIfEquals(Construct item1, Construct item2) {
						return (fCompareTypes && Static.getBoolean(sequals.exec(t, environment, item1, item2)))
								|| (!fCompareTypes && Static.getBoolean(equals.exec(t, environment, item1, item2)));
					}
				});
				for(Construct c : set) {
					newArray.push(c, t);
				}
				return newArray;
			}
		}

	@Override
	public CArray exec(final Target t, final Environment environment, Construct... args) throws ConfigRuntimeException {
	    CArray array = Static.getArray(args[0], t);
	    boolean compareTypes = true;
	    if (args.length == 2) {
		compareTypes = Static.getBoolean(args[1]);
	    }
	    final boolean fCompareTypes = compareTypes;
	    if (array.inAssociativeMode()) {
		return array.clone();
	    } else {
		List<Construct> asList = array.asList();
		CArray newArray = new CArray(t);
		Set<Construct> set = new LinkedComparatorSet<Construct>(asList, new LinkedComparatorSet.EqualsComparator<Construct>() {

		    @Override
		    public boolean checkIfEquals(Construct item1, Construct item2) {
			return (fCompareTypes && Static.getBoolean(sequals.exec(t, environment, item1, item2)))
				|| (!fCompareTypes && Static.getBoolean(equals.exec(t, environment, item1, item2)));
		    }
		});
		for (Construct c : set) {
		    newArray.push(c, t);
		}
		return newArray;
	    }
	}

Replace Generic With Diamond LinkedComparatorSet<Construct> with LinkedComparatorSet<> in method public exec(t Target, environment Environment, args Construct...) : CArray from class com.laytonsmith.core.functions.ArrayHandling.array_unique


	public static Script GenerateScript(ParseTree tree, String label){
		Script s = new Script();

		s.hasBeenCompiled = true;
		s.compilerError = false;
		s.cright = new ArrayList<>();
		s.cright.add(tree);
		s.label = label;

		return s;
	}

    public static Script GenerateScript(ParseTree tree, String label){
        Script s = new Script();

        s.hasBeenCompiled = true;
        s.compilerError = false;
        s.cright = new ArrayList<ParseTree>();
        s.cright.add(tree);
        s.label = label;

        return s;
    }

Replace Generic With Diamond ArrayList<ParseTree> with ArrayList<> in method public GenerateScript(tree ParseTree, label String) : Script from class com.laytonsmith.core.Script


	@Override
	public Map<MCEnchantment, Integer> getStoredEnchants() {
		Map<MCEnchantment,Integer> ret = new HashMap<>();
		for (Map.Entry<Enchantment,Integer> entry : es.getStoredEnchants().entrySet()) {
			ret.put(new BukkitMCEnchantment(entry.getKey()), entry.getValue());
		}
		return ret;
	}

	@Override
	public Map<MCEnchantment, Integer> getStoredEnchants() {
		Map<MCEnchantment,Integer> ret = new HashMap<MCEnchantment,Integer>();
		for (Map.Entry<Enchantment,Integer> entry : es.getStoredEnchants().entrySet()) {
			ret.put(new BukkitMCEnchantment(entry.getKey()), entry.getValue());
		}
		return ret;
	}

Replace Generic With Diamond HashMap<MCEnchantment,Integer> with HashMap<> in method public getStoredEnchants() : Map<MCEnchantment,Integer> from class com.laytonsmith.abstraction.bukkit.BukkitMCEnchantmentStorageMeta


		@Override
		public List<MCItemStack> getDrops() {
			List<ItemStack> islist = e.getDrops();
			List<MCItemStack> drops = new ArrayList<>();

			for(ItemStack is : islist){
				drops.add(new BukkitMCItemStack(is));
			}

			return drops;
		}

		@Override
		public List<MCItemStack> getDrops() {
            List<ItemStack> islist = e.getDrops();
            List<MCItemStack> drops = new ArrayList<MCItemStack>();

            for(ItemStack is : islist){
                drops.add(new BukkitMCItemStack(is));
            }

            return drops;
        }

Replace Generic With Diamond ArrayList<MCItemStack> with ArrayList<> in method public getDrops() : List<MCItemStack> from class com.laytonsmith.abstraction.bukkit.events.BukkitEntityEvents.BukkitMCEntityDeathEvent


		public static BukkitMCPlayerDeathEvent _instantiate(MCPlayer entity, List<MCItemStack> listOfDrops,
				int droppedExp, String deathMessage){
			List<ItemStack> drops = new ArrayList<>();

			return new BukkitMCPlayerDeathEvent(new PlayerDeathEvent(((BukkitMCPlayer)entity)._Player(), drops, droppedExp, deathMessage));
		}

        public static BukkitMCPlayerDeathEvent _instantiate(MCPlayer entity, List<MCItemStack> listOfDrops,
                int droppedExp, String deathMessage){
            List<ItemStack> drops = new ArrayList<ItemStack>();

            return new BukkitMCPlayerDeathEvent(new PlayerDeathEvent(((BukkitMCPlayer)entity)._Player(), drops, droppedExp, deathMessage));
        }

Replace Generic With Diamond ArrayList<ItemStack> with ArrayList<> in method public _instantiate(entity MCPlayer, listOfDrops List<MCItemStack>, droppedExp int, deathMessage String) : BukkitMCPlayerDeathEvent from class com.laytonsmith.abstraction.bukkit.events.BukkitPlayerEvents.BukkitMCPlayerDeathEvent


	@Override
	public Map<MCEnchantment, Integer> getEnchants() {
		Map<MCEnchantment, Integer> map = new HashMap<>();
		for(Entry<Enchantment, Integer> entry : im.getEnchants().entrySet()) {
			map.put(new BukkitMCEnchantment(entry.getKey()), entry.getValue());
		}
		return map;
	}

	@Override
	public Map<MCEnchantment, Integer> getEnchants() {
		Map<MCEnchantment, Integer> map = new HashMap<MCEnchantment, Integer>();
		for(Entry<Enchantment, Integer> entry : im.getEnchants().entrySet()) {
			map.put(new BukkitMCEnchantment(entry.getKey()), entry.getValue());
		}
		return map;
	}

Replace Generic With Diamond HashMap<MCEnchantment,Integer> with HashMap<> in method public getEnchants() : Map<MCEnchantment,Integer> from class com.laytonsmith.abstraction.bukkit.BukkitMCItemMeta


	@Override
	public Map<Character, MCItemStack> getIngredientMap() {
		Map<Character, MCItemStack> ret = new HashMap<>();
		for (Map.Entry<Character, ItemStack> e : r.getIngredientMap().entrySet()) {
			ret.put(e.getKey(), new BukkitMCItemStack(e.getValue()));
		}
		return ret;
	}

	@Override
	public Map<Character, MCItemStack> getIngredientMap() {
		Map<Character, MCItemStack> ret = new HashMap<Character, MCItemStack>();
		for (Map.Entry<Character, ItemStack> e : r.getIngredientMap().entrySet()) {
			ret.put(e.getKey(), new BukkitMCItemStack(e.getValue()));
		}
		return ret;
	}

Replace Generic With Diamond HashMap<Character,MCItemStack> with HashMap<> in method public getIngredientMap() : Map<Character,MCItemStack> from class com.laytonsmith.abstraction.bukkit.BukkitMCShapedRecipe


	@Override
	public List<MCItemStack> getIngredients() {
		List<MCItemStack> ret = new ArrayList<>();
		for (ItemStack is : r.getIngredientList()) {
			ret.add(new BukkitMCItemStack(is));
		}
		return ret;
	}

	@Override
	public List<MCItemStack> getIngredients() {
		List<MCItemStack> ret = new ArrayList<MCItemStack>();
		for (ItemStack is : r.getIngredientList()) {
			ret.add(new BukkitMCItemStack(is));
		}
		return ret;
	}

Replace Generic With Diamond ArrayList<MCItemStack> with ArrayList<> in method public getIngredients() : List<MCItemStack> from class com.laytonsmith.abstraction.bukkit.BukkitMCShapelessRecipe


	/**
	 * If you're in a hurry, and all you want is to get the output of System.out
	 * from a process started with a list of arguments, this will do it for you.
	 * @param args
	 * @return
	 */
	public static String Execute(String [] args) throws InterruptedException, IOException{
		final List<Byte> output = new ArrayList<>();
		CommandExecutor c = new CommandExecutor(args);
		OutputStream os = new BufferedOutputStream(new OutputStream() {

			@Override
			public void write(int next) throws IOException {
				output.add((byte)next);
			}
		});
		c.setSystemOut(os);
		c.start();
		c.waitFor();
		Byte[] Bytes = new Byte[output.size()];
		byte[] bytes = new byte[output.size()];
		Bytes = output.toArray(Bytes);
		for(int i = 0; i < Bytes.length; i++){
			bytes[i] = Bytes[i];
		}

		return new String(bytes, "UTF-8");
	}

	/**
	 * If you're in a hurry, and all you want is to get the output of System.out
	 * from a process started with a list of arguments, this will do it for you.
	 * @param args
	 * @return
	 */
	public static String Execute(String [] args) throws InterruptedException, IOException{
		final List<Byte> output = new ArrayList<Byte>();
		CommandExecutor c = new CommandExecutor(args);
		OutputStream os = new BufferedOutputStream(new OutputStream() {

			@Override
			public void write(int next) throws IOException {
				output.add((byte)next);
			}
		});
		c.setSystemOut(os);
		c.start();
		c.waitFor();
		Byte[] Bytes = new Byte[output.size()];
		byte[] bytes = new byte[output.size()];
		Bytes = output.toArray(Bytes);
		for(int i = 0; i < Bytes.length; i++){
			bytes[i] = Bytes[i];
		}

		return new String(bytes, "UTF-8");
	}

Replace Generic With Diamond ArrayList<Byte> with ArrayList<> in method public Execute(args String[]) : String from class com.laytonsmith.PureUtilities.CommandExecutor


		public FakeCore(){
			super(null, null, null, null, null);
			this.autoIncludes = new ArrayList<>();
		}

		public FakeCore(){
			super(null, null, null, null, null);
			this.autoIncludes = new ArrayList<File>();
		}

Replace Generic With Diamond ArrayList<File> with ArrayList<> in method public FakeCore() from class com.laytonsmith.core.functions.ExampleScript.FakeCore


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try {
				return new CInt(ba.getByte(pos), t);
			} catch(IndexOutOfBoundsException | BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try {
				return new CInt(ba.getByte(pos), t);
			} catch(IndexOutOfBoundsException e){
				throw new CRERangeException(e.getMessage(), t);
			} catch(BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

Merge Catch [catch(IndexOutOfBoundsException e), catch(BufferUnderflowException e)] to catch(IndexOutOfBoundsException|BufferUnderflowException e) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.ByteArrays.ba_get_byte


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try{
				return new CString(ba.getChar(pos), t);
			} catch(IndexOutOfBoundsException | BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try{
				return new CString(ba.getChar(pos), t);
			} catch(IndexOutOfBoundsException e){
				throw new CRERangeException(e.getMessage(), t);
			} catch(BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

Merge Catch [catch(IndexOutOfBoundsException e), catch(BufferUnderflowException e)] to catch(IndexOutOfBoundsException|BufferUnderflowException e) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.ByteArrays.ba_get_char


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try{
				return new CInt(ba.getShort(pos), t);
			} catch(IndexOutOfBoundsException | BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try{
				return new CInt(ba.getShort(pos), t);
			} catch(IndexOutOfBoundsException e){
				throw new CRERangeException(e.getMessage(), t);
			} catch(BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

Merge Catch [catch(IndexOutOfBoundsException e), catch(BufferUnderflowException e)] to catch(IndexOutOfBoundsException|BufferUnderflowException e) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.ByteArrays.ba_get_short


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try{
				return new CInt(ba.getInt(pos), t);
			} catch(IndexOutOfBoundsException | BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try{
				return new CInt(ba.getInt(pos), t);
			} catch(IndexOutOfBoundsException e){
				throw new CRERangeException(e.getMessage(), t);
			} catch(BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

Merge Catch [catch(IndexOutOfBoundsException e), catch(BufferUnderflowException e)] to catch(IndexOutOfBoundsException|BufferUnderflowException e) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.ByteArrays.ba_get_int


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try {
				return new CInt(ba.getLong(pos), t);
			} catch (IndexOutOfBoundsException | BufferUnderflowException e) {
				throw new CRERangeException(e.getMessage(), t);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try {
				return new CInt(ba.getLong(pos), t);
			} catch (IndexOutOfBoundsException e) {
				throw new CRERangeException(e.getMessage(), t);
			} catch (BufferUnderflowException e) {
				throw new CRERangeException(e.getMessage(), t);
			}
		}

Merge Catch [catch(IndexOutOfBoundsException e), catch(BufferUnderflowException e)] to catch(IndexOutOfBoundsException|BufferUnderflowException e) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.ByteArrays.ba_get_long


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try {
				return new CDouble(ba.getFloat(pos), t);
			} catch (IndexOutOfBoundsException | BufferUnderflowException e) {
				throw new CRERangeException(e.getMessage(), t);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try {
				return new CDouble(ba.getFloat(pos), t);
			} catch (IndexOutOfBoundsException e) {
				throw new CRERangeException(e.getMessage(), t);
			} catch (BufferUnderflowException e) {
				throw new CRERangeException(e.getMessage(), t);
			}
		}

Merge Catch [catch(IndexOutOfBoundsException e), catch(BufferUnderflowException e)] to catch(IndexOutOfBoundsException|BufferUnderflowException e) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.ByteArrays.ba_get_float


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try {
				return new CDouble(ba.getDouble(pos), t);
			} catch(IndexOutOfBoundsException | BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			try {
				return new CDouble(ba.getDouble(pos), t);
			} catch(IndexOutOfBoundsException e){
				throw new CRERangeException(e.getMessage(), t);
			} catch(BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

Merge Catch [catch(IndexOutOfBoundsException e), catch(BufferUnderflowException e)] to catch(IndexOutOfBoundsException|BufferUnderflowException e) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.ByteArrays.ba_get_double


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			int size = Static.getInt32(args[1], t);
			Integer pos = null;
			if(args.length == 3){
				pos = Static.getInt32(args[2], t);
			}
			try {
				return ba.getBytes(size, pos);
			} catch(IndexOutOfBoundsException | BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			int size = Static.getInt32(args[1], t);
			Integer pos = null;
			if(args.length == 3){
				pos = Static.getInt32(args[2], t);
			}
			try {
				return ba.getBytes(size, pos);
			} catch(IndexOutOfBoundsException e){
				throw new CRERangeException(e.getMessage(), t);
			} catch(BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			}
		}

Merge Catch [catch(IndexOutOfBoundsException e), catch(BufferUnderflowException e)] to catch(IndexOutOfBoundsException|BufferUnderflowException e) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.ByteArrays.ba_get_bytes


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			String encoding = null;
			if(args.length == 3){
				encoding = args[2].nval();
			}
			try{
				return new CString(ba.readUTF8String(pos, encoding), t);
			} catch(UnsupportedEncodingException e){
				throw new CREFormatException(e.getMessage(), t);
			} catch(IndexOutOfBoundsException | BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			} catch(NegativeArraySizeException e){
				throw new CREFormatException("Invalid data", t);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			CByteArray ba = getBA(args, t);
			Integer pos = get_getPos(args, t);
			String encoding = null;
			if(args.length == 3){
				encoding = args[2].nval();
			}
			try{
				return new CString(ba.readUTF8String(pos, encoding), t);
			} catch(UnsupportedEncodingException e){
				throw new CREFormatException(e.getMessage(), t);
			} catch(IndexOutOfBoundsException e){
				throw new CRERangeException(e.getMessage(), t);
			} catch(BufferUnderflowException e){
				throw new CRERangeException(e.getMessage(), t);
			} catch(NegativeArraySizeException e){
				throw new CREFormatException("Invalid data", t);
			}
		}

Merge Catch [catch(IndexOutOfBoundsException e), catch(BufferUnderflowException e)] to catch(IndexOutOfBoundsException|BufferUnderflowException e) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.ByteArrays.ba_get_string


	/**
	 * If the Reaction returned by GetReaction is to report the exception, this
	 * function should be used to standardize the report format. If the error
	 * message wouldn't be very useful by itself, or if a hint is desired, an
	 * optional message may be provided (null otherwise).
	 *
	 * @param e
	 * @param optionalMessage
	 */
	private static void DoReport(String message, String exceptionType, List<StackTraceElement> stacktrace, MCPlayer currentPlayer) {
		String type = exceptionType;
		if (exceptionType == null) {
			type = "FATAL";
		}
		List<StackTraceElement> st = new ArrayList<>(stacktrace);
		if (message == null) {
			message = "";
		}
		if (!"".equals(message.trim())) {
			message = ": " + message;
		}
		Target top = Target.UNKNOWN;
		StringBuilder log = new StringBuilder();
		StringBuilder console = new StringBuilder();
		StringBuilder player = new StringBuilder();
		log.append(type).append(message).append("\n");
		console.append(TermColors.RED).append(type).append(TermColors.WHITE).append(message).append("\n");
		player.append(MCChatColor.RED).append(type).append(MCChatColor.WHITE).append(message).append("\n");
		for (StackTraceElement e : st) {
			Target t = e.getDefinedAt();
			if (top == Target.UNKNOWN) {
				top = t;
			}
			String proc = e.getProcedureName();
			File file = t.file();
			int line = t.line();
			int column = t.col();
			String filepath;
			String simplepath;
			if (file == null) {
				filepath = simplepath = "Unknown Source";
			} else {
				filepath = file.getPath();
				simplepath = file.getName();
			}

			log.append("\t").append(proc).append(":").append(filepath).append(":")
					.append(line)/*.append(".")
					 .append(column)*/.append("\n");
			console.append("\t").append(TermColors.GREEN).append(proc)
					.append(TermColors.WHITE).append(":")
					.append(TermColors.YELLOW).append(filepath)
					.append(TermColors.WHITE).append(":")
					.append(TermColors.CYAN).append(line)/*.append(".").append(column)*/.append("\n");
			player.append("\t").append(MCChatColor.GREEN).append(proc)
					.append(MCChatColor.WHITE).append(":")
					.append(MCChatColor.YELLOW).append(simplepath)
					.append(MCChatColor.WHITE).append(":")
					.append(MCChatColor.AQUA).append(line)/*.append(".").append(column)*/.append("\n");

		}

		//Log
		//Don't log to screen though, since we're ALWAYS going to do that ourselves.
		CHLog.GetLogger().Log("COMPILE ERROR".equals(exceptionType) ? CHLog.Tags.COMPILER : CHLog.Tags.RUNTIME,
				LogLevel.ERROR, log.toString(), top, false);
		//Console
		StreamUtils.GetSystemOut().println(console.toString() + TermColors.reset());
		//Player
		if (currentPlayer != null) {
			currentPlayer.sendMessage(player.toString());
		}
	}

	/**
	 * If the Reaction returned by GetReaction is to report the exception, this
	 * function should be used to standardize the report format. If the error
	 * message wouldn't be very useful by itself, or if a hint is desired, an
	 * optional message may be provided (null otherwise).
	 *
	 * @param e
	 * @param optionalMessage
	 */
	private static void DoReport(String message, String exceptionType, List<StackTraceElement> stacktrace, MCPlayer currentPlayer) {
		String type = exceptionType;
		if (exceptionType == null) {
			type = "FATAL";
		}
		List<StackTraceElement> st = new ArrayList<StackTraceElement>(stacktrace);
		if (message == null) {
			message = "";
		}
		if (!"".equals(message.trim())) {
			message = ": " + message;
		}
		Target top = Target.UNKNOWN;
		StringBuilder log = new StringBuilder();
		StringBuilder console = new StringBuilder();
		StringBuilder player = new StringBuilder();
		log.append(type).append(message).append("\n");
		console.append(TermColors.RED).append(type).append(TermColors.WHITE).append(message).append("\n");
		player.append(MCChatColor.RED).append(type).append(MCChatColor.WHITE).append(message).append("\n");
		for (StackTraceElement e : st) {
			Target t = e.getDefinedAt();
			if (top == Target.UNKNOWN) {
				top = t;
			}
			String proc = e.getProcedureName();
			File file = t.file();
			int line = t.line();
			int column = t.col();
			String filepath;
			String simplepath;
			if (file == null) {
				filepath = simplepath = "Unknown Source";
			} else {
				filepath = file.getPath();
				simplepath = file.getName();
			}

			log.append("\t").append(proc).append(":").append(filepath).append(":")
					.append(line)/*.append(".")
					 .append(column)*/.append("\n");
			console.append("\t").append(TermColors.GREEN).append(proc)
					.append(TermColors.WHITE).append(":")
					.append(TermColors.YELLOW).append(filepath)
					.append(TermColors.WHITE).append(":")
					.append(TermColors.CYAN).append(line)/*.append(".").append(column)*/.append("\n");
			player.append("\t").append(MCChatColor.GREEN).append(proc)
					.append(MCChatColor.WHITE).append(":")
					.append(MCChatColor.YELLOW).append(simplepath)
					.append(MCChatColor.WHITE).append(":")
					.append(MCChatColor.AQUA).append(line)/*.append(".").append(column)*/.append("\n");

		}

		//Log
		//Don't log to screen though, since we're ALWAYS going to do that ourselves.
		CHLog.GetLogger().Log("COMPILE ERROR".equals(exceptionType) ? CHLog.Tags.COMPILER : CHLog.Tags.RUNTIME,
				LogLevel.ERROR, log.toString(), top, false);
		//Console
		StreamUtils.GetSystemOut().println(console.toString() + TermColors.reset());
		//Player
		if (currentPlayer != null) {
			currentPlayer.sendMessage(player.toString());
		}
	}

Replace Generic With Diamond ArrayList<StackTraceElement> with ArrayList<> in method private DoReport(message String, exceptionType String, stacktrace List<StackTraceElement>, currentPlayer MCPlayer) : void from class com.laytonsmith.core.exceptions.ConfigRuntimeException


		@Override
        public BindableEvent convert(CArray manual, Target t) {
            //For firing off the event manually, we have to convert the CArray into an
            //actual object that will trigger it
            String splayer = manual.get("player", Target.UNKNOWN).val();
            List<MCItemStack> list = new ArrayList<>();
            String deathMessage = manual.get("death_message", Target.UNKNOWN).val();
            CArray clist = (CArray)manual.get("drops", Target.UNKNOWN);
            for(String key : clist.stringKeySet()){
                list.add(ObjectGenerator.GetGenerator().item(clist.get(key, Target.UNKNOWN), clist.getTarget()));
            }
            MCPlayerDeathEvent e = EventBuilder.instantiate(MCPlayerDeathEvent.class, Static.GetPlayer(splayer, Target.UNKNOWN), list,
                    0, deathMessage);
            return e;
        }

		@Override
        public BindableEvent convert(CArray manual, Target t) {
            //For firing off the event manually, we have to convert the CArray into an
            //actual object that will trigger it
            String splayer = manual.get("player", Target.UNKNOWN).val();
            List<MCItemStack> list = new ArrayList<MCItemStack>();
            String deathMessage = manual.get("death_message", Target.UNKNOWN).val();
            CArray clist = (CArray)manual.get("drops", Target.UNKNOWN);
            for(String key : clist.stringKeySet()){
                list.add(ObjectGenerator.GetGenerator().item(clist.get(key, Target.UNKNOWN), clist.getTarget()));
            }
            MCPlayerDeathEvent e = EventBuilder.instantiate(MCPlayerDeathEvent.class, Static.GetPlayer(splayer, Target.UNKNOWN), list,
                    0, deathMessage);
            return e;
        }

Replace Generic With Diamond ArrayList<MCItemStack> with ArrayList<> in method public convert(manual CArray, t Target) : BindableEvent from class com.laytonsmith.core.events.drivers.PlayerEvents.player_death


	/**
	 * Sets up CommandHelper to play-dirty, if the user has specified as such
	 */
	public static void PlayDirty() {
		if (Prefs.PlayDirty()) {
			try {
				//Set up our "proxy"
				BukkitDirtyRegisteredListener.Repopulate();
			} catch (NoSuchMethodException ex) {
				Logger.getLogger(Static.class.getName()).log(Level.SEVERE, null, ex);
			} catch (NoSuchFieldException | ClassCastException | IllegalArgumentException | IllegalAccessException ex) {
				Static.getLogger().log(Level.SEVERE, "Uh oh, play dirty mode isn't working.", ex);
			}
		} //else play nice :(
	}

	/**
	 * Sets up CommandHelper to play-dirty, if the user has specified as such
	 */
	public static void PlayDirty() {
		if (Prefs.PlayDirty()) {
			try {
				//Set up our "proxy"
				BukkitDirtyRegisteredListener.Repopulate();
			} catch (NoSuchMethodException ex) {
				Logger.getLogger(Static.class.getName()).log(Level.SEVERE, null, ex);
			} catch (NoSuchFieldException ex) {
				AliasCore.logger.log(Level.SEVERE, "Uh oh, play dirty mode isn't working.", ex);
			} catch (ClassCastException ex) {
				AliasCore.logger.log(Level.SEVERE, "Uh oh, play dirty mode isn't working.", ex);
			} catch (IllegalArgumentException ex) {
				AliasCore.logger.log(Level.SEVERE, "Uh oh, play dirty mode isn't working.", ex);
			} catch (IllegalAccessException ex) {
				AliasCore.logger.log(Level.SEVERE, "Uh oh, play dirty mode isn't working.", ex);
			}
		} //else play nice :(
	}

Merge Catch [catch(NoSuchFieldException ex), catch(ClassCastException ex), catch(IllegalArgumentException ex), catch(IllegalAccessException ex)] to catch(NoSuchFieldException|ClassCastException|IllegalArgumentException|IllegalAccessException ex) in method public PlayDirty() : void from class com.laytonsmith.commandhelper.BukkitDirtyRegisteredListener


		public static ParseTree getParseTree(ParseTree child, FileOptions fo, Target t) {
			CFunction ac = new CFunction(new __autoconcat__().getName(), t);
			ParseTree tree = new ParseTree(ac, fo);
			List<ParseTree> children = new ArrayList<>();
			children.add(child);
			tree.setChildren(children);
			return tree;
		}

		public static ParseTree getParseTree(ParseTree child, FileOptions fo, Target t) {
			CFunction ac = new CFunction(new __autoconcat__().getName(), t);
			ParseTree tree = new ParseTree(ac, fo);
			List<ParseTree> children = new ArrayList<ParseTree>();
			children.add(child);
			tree.setChildren(children);
			return tree;
		}

Replace Generic With Diamond ArrayList<ParseTree> with ArrayList<> in method public getParseTree(child ParseTree, fo FileOptions, t Target) : ParseTree from class com.laytonsmith.core.functions.Compiler.__autoconcat__


	/**
	 * Does the class discovery for this particular URL. This should only be
	 * called by doDiscovery. Other internal methods should call doDiscovery,
	 * which handles looking through the dirtyURLs.
	 */
	private synchronized void discover(URL rootLocation) {
		long start = System.currentTimeMillis();
		if(debug){
			System.out.println("Beginning discovery of " + rootLocation);
		}
		try {
			//If the ClassDiscoveryCache is set, just use this.
			if(classDiscoveryCache != null){
				ClassDiscoveryURLCache cduc = classDiscoveryCache.getURLCache(rootLocation);
				preCaches.put(rootLocation, cduc);
			}

			String url;
			try {
				url = URLDecoder.decode(rootLocation.toString(), "UTF8");
			} catch (UnsupportedEncodingException ex) {
				url = URLDecoder.decode(rootLocation.toString());
			}

			if (url == null) {
				url = GetClassContainer(ClassDiscovery.class).toString();
			}
			final File rootLocationFile;
			if (!classCache.containsKey(rootLocation)) {
				classCache.put(rootLocation, Collections.synchronizedSet(new HashSet<ClassMirror<?>>()));
			} else {
				classCache.get(rootLocation).clear();
			}
			final Set<ClassMirror<?>> mirrors = classCache.get(rootLocation);
			if (preCaches.containsKey(rootLocation)) {
				if(debug){
					System.out.println("Precache already contains this URL, so using it");
				}
				//No need, already got a cache for this url
				mirrors.addAll(preCaches.get(rootLocation).getClasses());
				return;
			}
			if(debug){
				System.out.println("Precache does not contain data for this URL, so scanning now.");
			}
			url = url.replaceFirst("^jar:", "");
			if (url.endsWith("!/")) {
				url = StringUtils.replaceLast(url, "!/", "");
			}
			if (url.startsWith("file:") && !url.endsWith(".jar")) {
				final AtomicInteger id = new AtomicInteger(0);
//				ExecutorService service = Executors.newFixedThreadPool(10, new ThreadFactory() {
//					@Override
//					public Thread newThread(Runnable r) {
//						return new Thread(r, "ClassDiscovery-Async-" + id.incrementAndGet());
//					}
//				});

				//Remove file: from the front
				String root = url.substring(5);
				rootLocationFile = new File(root);
				List<File> fileList = new ArrayList<>();
				descend(new File(root), fileList);

				//Now, we have all the class files in the package. But, it's the absolute path
				//to all of them. We have to first remove the "front" part
				for (File f : fileList) {
					String file = f.toString();
					if (!file.matches(".*\\$(?:\\d)*\\.class") && file.endsWith(".class")) {
						InputStream stream = null;
						try {
							stream = FileUtil.readAsStream(new File(rootLocationFile,
									f.getAbsolutePath().replaceFirst(Pattern.quote(new File(root).getAbsolutePath() + File.separator), "")));
							ClassMirror cm = new ClassMirror(stream, new URL(url));
							mirrors.add(cm);
						} catch (IOException ex) {
							Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
						} finally {
							if (stream != null) {
								try {
									stream.close();
								} catch (IOException ex) {
									Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
								}
							}
						}
					}
				}
//				service.shutdown();
//				try {
//					//Doesn't look like 0 is an option, so we'll just wait a day.
//					service.awaitTermination(1, TimeUnit.DAYS);
//				} catch (InterruptedException ex) {
//					Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
//				}
			} else if (url.startsWith("file:") && url.endsWith(".jar")) {
				//We are running from a jar
				url = url.replaceFirst("file:", "");
				rootLocationFile = new File(url);
				ZipIterator zi = new ZipIterator(rootLocationFile);
				try {
					zi.iterate(new ZipIterator.ZipIteratorCallback() {
						@Override
						public void handle(String filename, InputStream in) {
							if (!filename.matches(".*\\$(?:\\d)*\\.class") && filename.endsWith(".class")) {
								try {
									ClassMirror cm = new ClassMirror(in, rootLocationFile.toURI().toURL());
									mirrors.add(cm);
								} catch (IOException ex) {
									Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
								}

							}
						}
					}, progressIterator);
				} catch (IOException ex) {
					Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
				}
			} else {
				throw new RuntimeException("Unknown url type: " + rootLocation);
			}
		} finally {
			if(debug){
				System.out.println("Scans finished for " + rootLocation + ", taking " + (System.currentTimeMillis() - start) + " ms.");
			}
		}
	}

	/**
	 * Does the class discovery for this particular URL. This should only be
	 * called by doDiscovery. Other internal methods should call doDiscovery,
	 * which handles looking through the dirtyURLs.
	 */
	private synchronized void discover(URL rootLocation) {
		long start = System.currentTimeMillis();
		if(debug){
			System.out.println("Beginning discovery of " + rootLocation);
		}
		try {
			//If the ClassDiscoveryCache is set, just use this.
			if(classDiscoveryCache != null){
				ClassDiscoveryURLCache cduc = classDiscoveryCache.getURLCache(rootLocation);
				preCaches.put(rootLocation, cduc);
			}

			String url;
			try {
				url = URLDecoder.decode(rootLocation.toString(), "UTF8");
			} catch (UnsupportedEncodingException ex) {
				url = URLDecoder.decode(rootLocation.toString());
			}

			if (url == null) {
				url = GetClassContainer(ClassDiscovery.class).toString();
			}
			final File rootLocationFile;
			if (!classCache.containsKey(rootLocation)) {
				classCache.put(rootLocation, Collections.synchronizedSet(new HashSet<ClassMirror<?>>()));
			} else {
				classCache.get(rootLocation).clear();
			}
			final Set<ClassMirror<?>> mirrors = classCache.get(rootLocation);
			if (preCaches.containsKey(rootLocation)) {
				if(debug){
					System.out.println("Precache already contains this URL, so using it");
				}
				//No need, already got a cache for this url
				mirrors.addAll(preCaches.get(rootLocation).getClasses());
				return;
			}
			if(debug){
				System.out.println("Precache does not contain data for this URL, so scanning now.");
			}
			url = url.replaceFirst("^jar:", "");
			if (url.endsWith("!/")) {
				url = StringUtils.replaceLast(url, "!/", "");
			}
			if (url.startsWith("file:") && !url.endsWith(".jar")) {
				final AtomicInteger id = new AtomicInteger(0);
//				ExecutorService service = Executors.newFixedThreadPool(10, new ThreadFactory() {
//					@Override
//					public Thread newThread(Runnable r) {
//						return new Thread(r, "ClassDiscovery-Async-" + id.incrementAndGet());
//					}
//				});

				//Remove file: from the front
				String root = url.substring(5);
				rootLocationFile = new File(root);
				List<File> fileList = new ArrayList<File>();
				descend(new File(root), fileList);

				//Now, we have all the class files in the package. But, it's the absolute path
				//to all of them. We have to first remove the "front" part
				for (File f : fileList) {
					String file = f.toString();
					if (!file.matches(".*\\$(?:\\d)*\\.class") && file.endsWith(".class")) {
						InputStream stream = null;
						try {
							stream = FileUtil.readAsStream(new File(rootLocationFile,
									f.getAbsolutePath().replaceFirst(Pattern.quote(new File(root).getAbsolutePath() + File.separator), "")));
							ClassMirror cm = new ClassMirror(stream, new URL(url));
							mirrors.add(cm);
						} catch (IOException ex) {
							Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
						} finally {
							if (stream != null) {
								try {
									stream.close();
								} catch (IOException ex) {
									Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
								}
							}
						}
					}
				}
//				service.shutdown();
//				try {
//					//Doesn't look like 0 is an option, so we'll just wait a day.
//					service.awaitTermination(1, TimeUnit.DAYS);
//				} catch (InterruptedException ex) {
//					Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
//				}
			} else if (url.startsWith("file:") && url.endsWith(".jar")) {
				//We are running from a jar
				url = url.replaceFirst("file:", "");
				rootLocationFile = new File(url);
				ZipIterator zi = new ZipIterator(rootLocationFile);
				try {
					zi.iterate(new ZipIterator.ZipIteratorCallback() {
						@Override
						public void handle(String filename, InputStream in) {
							if (!filename.matches(".*\\$(?:\\d)*\\.class") && filename.endsWith(".class")) {
								try {
									ClassMirror cm = new ClassMirror(in, rootLocationFile.toURI().toURL());
									mirrors.add(cm);
								} catch (IOException ex) {
									Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
								}

							}
						}
					}, progressIterator);
				} catch (IOException ex) {
					Logger.getLogger(ClassDiscovery.class.getName()).log(Level.SEVERE, null, ex);
				}
			} else {
				throw new RuntimeException("Unknown url type: " + rootLocation);
			}
		} finally {
			if(debug){
				System.out.println("Scans finished for " + rootLocation + ", taking " + (System.currentTimeMillis() - start) + " ms.");
			}
		}
	}

Replace Generic With Diamond ArrayList<File> with ArrayList<> in method private discover(rootLocation URL) : void from class com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery


	/**
	 * Returns a list of all known classes. The ClassMirror for each class is
	 * returned, and further examination can be done on each class, or loadClass
	 * can be called on the ClassMirror to get the actual Class object. No
	 * ClassLoaders are involved directly in this operation.
	 *
	 * @return A list of ClassMirror objects for all known classes
	 */
	public Set<ClassMirror<?>> getKnownClasses() {
		doDiscovery();
		Set<ClassMirror<?>> ret = new HashSet<>();
		for (URL url : urlCache) {
			ret.addAll(getKnownClasses(url));
		}
		return ret;
	}

	/**
	 * Returns a list of all known classes. The ClassMirror for each class is
	 * returned, and further examination can be done on each class, or loadClass
	 * can be called on the ClassMirror to get the actual Class object. No
	 * ClassLoaders are involved directly in this operation.
	 *
	 * @return A list of ClassMirror objects for all known classes
	 */
	public Set<ClassMirror<?>> getKnownClasses() {
		doDiscovery();
		Set<ClassMirror<?>> ret = new HashSet<ClassMirror<?>>();
		for (URL url : urlCache) {
			ret.addAll(getKnownClasses(url));
		}
		return ret;
	}

Replace Generic With Diamond HashSet<ClassMirror<?>> with HashSet<> in method public getKnownClasses() : Set<ClassMirror<?>> from class com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery


	/**
	 * Gets all known classes, only within this URL. If this url isn't in the
	 * list of discovery locations, it is automatically added, via
	 * {@link #addDiscoveryLocation(java.net.URL)}.
	 *
	 * @param url
	 * @return
	 */
	public List<ClassMirror<?>> getKnownClasses(URL url) {
		if (url == null) {
			throw new NullPointerException("url cannot be null");
		}
		if (!classCache.containsKey(url)) {
			addDiscoveryLocation(url);
		}
		doDiscovery();
		return new ArrayList<>(classCache.get(url));
	}

	/**
	 * Gets all known classes, only within this URL. If this url isn't in the
	 * list of discovery locations, it is automatically added, via
	 * {@link #addDiscoveryLocation(java.net.URL)}.
	 *
	 * @param url
	 * @return
	 */
	public List<ClassMirror<?>> getKnownClasses(URL url) {
		if (url == null) {
			throw new NullPointerException("url cannot be null");
		}
		if (!classCache.containsKey(url)) {
			addDiscoveryLocation(url);
		}
		doDiscovery();
		return new ArrayList<ClassMirror<?>>(classCache.get(url));
	}

Replace Generic With Diamond ArrayList<ClassMirror<?>> with ArrayList<> in method public getKnownClasses(url URL) : List<ClassMirror<?>> from class com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery


	/**
	 * Unlike {@link #getClassesThatExtend(java.lang.Class)}, this actually
	 * loads the matching classes into PermGen, and returns a Set of these
	 * classes. This is useful if you are for sure going to use these classes
	 * immediately, and don't want to have to lazy load them individually.
	 *
	 * @param <T>
	 * @param superType
	 * @param loader
	 * @param initialize
	 * @return
	 */
	public <T> Set<Class<T>> loadClassesThatExtend(Class<T> superType, ClassLoader loader, boolean initialize) {
		Set<Class<T>> set = new HashSet<>();
		for (ClassMirror<T> cm : getClassesThatExtend(superType)) {
			set.add(cm.loadClass(loader, initialize));
		}
		return set;
	}

	/**
	 * Unlike {@link #getClassesThatExtend(java.lang.Class)}, this actually
	 * loads the matching classes into PermGen, and returns a Set of these
	 * classes. This is useful if you are for sure going to use these classes
	 * immediately, and don't want to have to lazy load them individually.
	 *
	 * @param <T>
	 * @param superType
	 * @param loader
	 * @param initialize
	 * @return
	 */
	public <T> Set<Class<T>> loadClassesThatExtend(Class<T> superType, ClassLoader loader, boolean initialize) {
		Set<Class<T>> set = new HashSet<Class<T>>();
		for (ClassMirror<T> cm : getClassesThatExtend(superType)) {
			set.add(cm.loadClass(loader, initialize));
		}
		return set;
	}

Replace Generic With Diamond HashSet<Class<T>> with HashSet<> in method public loadClassesThatExtend(superType Class<T>, loader ClassLoader, initialize boolean) : Set<Class<T>> from class com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery


	/**
	 * Unlike {@link #getClassesWithAnnotationThatExtend(java.lang.Class, java.lang.Class)}, this actually
	 * loads the matching classes into PermGen, and returns a Set of these classes.
	 * This is useful if you are for sure going to use these classes immediately, and don't want to have
	 * to lazy load them individually.
	 * @param <T> The type that will be returned, based on superClass
	 * @param annotation The annotation that the classes should be tagged with
	 * @param superClass The super class that the classes should extend
	 * @param loader
	 * @param initialize
	 * @return A set of classes that match the criteria
	 */
	public <T> Set<Class<T>> loadClassesWithAnnotationThatExtend(Class<? extends Annotation> annotation, Class<T> superClass, ClassLoader loader, boolean initialize){
		Set<Class<T>> set = new HashSet<>();
		for (ClassMirror<T> cm : getClassesWithAnnotationThatExtend(annotation, superClass)) {
			try {
				set.add(cm.loadClass(loader, initialize));
			} catch (NoClassDefFoundError e) {
				//Ignore this for now?
				//throw new Error("While trying to process " + cm.toString() + ", an error occurred.", e);
			}
		}
		return set;
	}

	/**
	 * Unlike {@link #getClassesWithAnnotationThatExtend(java.lang.Class, java.lang.Class)}, this actually
	 * loads the matching classes into PermGen, and returns a Set of these classes.
	 * This is useful if you are for sure going to use these classes immediately, and don't want to have
	 * to lazy load them individually.
	 * @param <T> The type that will be returned, based on superClass
	 * @param annotation The annotation that the classes should be tagged with
	 * @param superClass The super class that the classes should extend
	 * @param loader
	 * @param initialize
	 * @return A set of classes that match the criteria
	 */
	public <T> Set<Class<T>> loadClassesWithAnnotationThatExtend(Class<? extends Annotation> annotation, Class<T> superClass, ClassLoader loader, boolean initialize){
		Set<Class<T>> set = new HashSet<Class<T>>();
		for (ClassMirror<T> cm : getClassesWithAnnotationThatExtend(annotation, superClass)) {
			try {
				set.add(cm.loadClass(loader, initialize));
			} catch (NoClassDefFoundError e) {
				//Ignore this for now?
				//throw new Error("While trying to process " + cm.toString() + ", an error occurred.", e);
			}
		}
		return set;
	}

Replace Generic With Diamond HashSet<Class<T>> with HashSet<> in method public loadClassesWithAnnotationThatExtend(annotation Class<? extends Annotation>, superClass Class<T>, loader ClassLoader, initialize boolean) : Set<Class<T>> from class com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery


	/**
	 * Unlike {@link #getClassesWithAnnotation(java.lang.Class)}, this actually
	 * loads the matching classes into PermGen, and returns a Set of these
	 * classes. This is useful if you are for sure going to use these classes
	 * immediately, and don't want to have to lazy load them individually.
	 *
	 * @param annotation
	 * @param loader
	 * @param initialize
	 * @return
	 */
	public Set<Class> loadClassesWithAnnotation(Class<? extends Annotation> annotation, ClassLoader loader, boolean initialize) {
		Set<Class> set = new HashSet<>();
		for (ClassMirror<?> cm : getClassesWithAnnotation(annotation)) {
			try {
				set.add(cm.loadClass(loader, initialize));
			} catch (NoClassDefFoundError e) {
				//Ignore this for now?
				//throw new Error("While trying to process " + cm.toString() + ", an error occurred.", e);
			}
		}
		return set;
	}

	/**
	 * Unlike {@link #getClassesWithAnnotation(java.lang.Class)}, this actually
	 * loads the matching classes into PermGen, and returns a Set of these
	 * classes. This is useful if you are for sure going to use these classes
	 * immediately, and don't want to have to lazy load them individually.
	 *
	 * @param annotation
	 * @param loader
	 * @param initialize
	 * @return
	 */
	public Set<Class> loadClassesWithAnnotation(Class<? extends Annotation> annotation, ClassLoader loader, boolean initialize) {
		Set<Class> set = new HashSet<Class>();
		for (ClassMirror<?> cm : getClassesWithAnnotation(annotation)) {
			try {
				set.add(cm.loadClass(loader, initialize));
			} catch (NoClassDefFoundError e) {
				//Ignore this for now?
				//throw new Error("While trying to process " + cm.toString() + ", an error occurred.", e);
			}
		}
		return set;
	}

Replace Generic With Diamond HashSet<Class> with HashSet<> in method public loadClassesWithAnnotation(annotation Class<? extends Annotation>, loader ClassLoader, initialize boolean) : Set<Class> from class com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery


	/**
	 * Unlike {@link #getMethodsWithAnnotation(java.lang.Class)}, this actually
	 * loads the matching method's containing classes into PermGen, and returns
	 * a Set of Method objects. This is useful if you are for sure going to use
	 * these methods immediately, and don't want to have to lazy load them
	 * individually.
	 *
	 * @param annotation
	 * @param loader
	 * @param initialize
	 * @return
	 */
	public Set<Method> loadMethodsWithAnnotation(Class<? extends Annotation> annotation, ClassLoader loader, boolean initialize) {
		try {
			Set<Method> set = new HashSet<>();
			for (MethodMirror mm : getMethodsWithAnnotation(annotation)) {
				set.add(mm.loadMethod(loader, initialize));
			}
			return set;
		} catch (ClassNotFoundException ex) {
			throw new NoClassDefFoundError();
		}
	}

	/**
	 * Unlike {@link #getMethodsWithAnnotation(java.lang.Class)}, this actually
	 * loads the matching method's containing classes into PermGen, and returns
	 * a Set of Method objects. This is useful if you are for sure going to use
	 * these methods immediately, and don't want to have to lazy load them
	 * individually.
	 *
	 * @param annotation
	 * @param loader
	 * @param initialize
	 * @return
	 */
	public Set<Method> loadMethodsWithAnnotation(Class<? extends Annotation> annotation, ClassLoader loader, boolean initialize) {
		try {
			Set<Method> set = new HashSet<Method>();
			for (MethodMirror mm : getMethodsWithAnnotation(annotation)) {
				set.add(mm.loadMethod(loader, initialize));
			}
			return set;
		} catch (ClassNotFoundException ex) {
			throw new NoClassDefFoundError();
		}
	}

Replace Generic With Diamond HashSet<Method> with HashSet<> in method public loadMethodsWithAnnotation(annotation Class<? extends Annotation>, loader ClassLoader, initialize boolean) : Set<Method> from class com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery


	/**
	 * Returns a class given a "fuzzy" package name, that is, the package name
	 * provided is a regex. The class name must match exactly, but the package
	 * name will be the closest match, or undefined if there is no clear
	 * candidate. If no matches are found, null is returned.
	 *
	 * @param packageRegex
	 * @param className
	 * @param initialize
	 * @param classLoader
	 * @return
	 */
	public ClassMirror forFuzzyName(String packageRegex, String className, boolean initialize, ClassLoader classLoader) {
		String index = packageRegex + className;
		if (fuzzyClassCache.containsKey(index)) {
			return fuzzyClassCache.get(index);
		}
		Set<ClassMirror> found = new HashSet<>();
		Set<ClassMirror<?>> searchSpace = getKnownClasses();
		for (ClassMirror c : searchSpace) {
			if (c.getPackage().getName().matches(packageRegex) && c.getSimpleName().equals(className)) {
				found.add(c);
			}
		}
		ClassMirror find;
		if (found.size() == 1) {
			find = found.iterator().next();
		} else if (found.isEmpty()) {
			find = null;
		} else {
			ClassMirror candidate = null;
			int max = Integer.MAX_VALUE;
			for (ClassMirror f : found) {
				int distance = StringUtils.LevenshteinDistance(f.getPackage().getName(), packageRegex);
				if (distance < max) {
					candidate = f;
					max = distance;
				}
			}
			find = candidate;
		}
		fuzzyClassCache.put(index, find);
		return find;
	}

	/**
	 * Returns a class given a "fuzzy" package name, that is, the package name
	 * provided is a regex. The class name must match exactly, but the package
	 * name will be the closest match, or undefined if there is no clear
	 * candidate. If no matches are found, null is returned.
	 *
	 * @param packageRegex
	 * @param className
	 * @param initialize
	 * @param classLoader
	 * @return
	 */
	public ClassMirror forFuzzyName(String packageRegex, String className, boolean initialize, ClassLoader classLoader) {
		String index = packageRegex + className;
		if (fuzzyClassCache.containsKey(index)) {
			return fuzzyClassCache.get(index);
		}
		Set<ClassMirror> found = new HashSet<ClassMirror>();
		Set<ClassMirror<?>> searchSpace = getKnownClasses();
		for (ClassMirror c : searchSpace) {
			if (c.getPackage().getName().matches(packageRegex) && c.getSimpleName().equals(className)) {
				found.add(c);
			}
		}
		ClassMirror find;
		if (found.size() == 1) {
			find = found.iterator().next();
		} else if (found.isEmpty()) {
			find = null;
		} else {
			ClassMirror candidate = null;
			int max = Integer.MAX_VALUE;
			for (ClassMirror f : found) {
				int distance = StringUtils.LevenshteinDistance(f.getPackage().getName(), packageRegex);
				if (distance < max) {
					candidate = f;
					max = distance;
				}
			}
			find = candidate;
		}
		fuzzyClassCache.put(index, find);
		return find;
	}

Replace Generic With Diamond HashSet<ClassMirror> with HashSet<> in method public forFuzzyName(packageRegex String, className String, initialize boolean, classLoader ClassLoader) : ClassMirror from class com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery


	/**
	 * Constructs a new instance of the specified object, using the constructor
	 * that matches the argument types, and passes in the arguments specified.
	 * It will bypass access restrictions if possible.
	 *
	 * @param <T> The class type returned, specified by the class type requested
	 * @param clazz
	 * @param argTypes
	 * @param args
	 * @return
	 * @throws ReflectionException
	 */
	public static <T> T newInstance(Class<T> clazz, Class[] argTypes, Object[] args) throws ReflectionException {
		try {
			Constructor<T> c = clazz.getDeclaredConstructor(argTypes);
			c.setAccessible(true);
			return c.newInstance(args);
		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException ex) {
			throw new ReflectionException(ex);
		}
	}

	/**
	 * Constructs a new instance of the specified object, using the constructor
	 * that matches the argument types, and passes in the arguments specified.
	 * It will bypass access restrictions if possible.
	 *
	 * @param <T> The class type returned, specified by the class type requested
	 * @param clazz
	 * @param argTypes
	 * @param args
	 * @return
	 * @throws com.laytonsmith.PureUtilities.ReflectionUtils.ReflectionException
	 */
	public static <T> T newInstance(Class<T> clazz, Class[] argTypes, Object[] args) throws ReflectionException {
		try {
			Constructor<T> c = clazz.getDeclaredConstructor(argTypes);
			c.setAccessible(true);
			return c.newInstance(args);
		} catch (InstantiationException ex) {
			throw new ReflectionException(ex);
		} catch (IllegalAccessException ex) {
			throw new ReflectionException(ex);
		} catch (IllegalArgumentException ex) {
			throw new ReflectionException(ex);
		} catch (InvocationTargetException ex) {
			throw new ReflectionException(ex);
		} catch (NoSuchMethodException ex) {
			throw new ReflectionException(ex);
		} catch (SecurityException ex) {
			throw new ReflectionException(ex);
		}
	}

Merge Catch [catch(InstantiationException ex), catch(IllegalAccessException ex), catch(IllegalArgumentException ex), catch(InvocationTargetException ex), catch(NoSuchMethodException ex), catch(SecurityException ex)] to catch(InstantiationException|IllegalAccessException|IllegalArgumentException|InvocationTargetException|NoSuchMethodException|SecurityException ex) in method public newInstance(clazz Class<T>, argTypes Class[], args Object[]) : T from class com.laytonsmith.PureUtilities.Common.ReflectionUtils


	/**
	 * Gets a member from a class, disregarding the access restrictions. If
	 * accessing a static variable, the instance may be null. If variableName
	 * contains a dot, then it recursively digs down and grabs that value. So,
	 * given the following class definitions:
	 * <pre>
	 * class A { B bObj; }
	 * class B { C cObj; }
	 * class C { String obj; }
	 * </pre> Then if clazz were A.class, and variableName were "bObj.cObj.obj",
	 * then C's String obj would be returned.
	 *
	 * @param clazz
	 * @param instance
	 * @param variableName
	 * @return
	 */
	public static Object get(Class clazz, Object instance, String variableName) throws ReflectionException {
		try {
			if (variableName.contains(".")) {
				String split[] = variableName.split("\\.");
				Object myInstance = instance;
				Class myClazz = clazz;
				for (String var : split) {
					myInstance = get(myClazz, myInstance, var);
					myClazz = myInstance.getClass();
				}
				return myInstance;
			} else {
				Field f = clazz.getDeclaredField(variableName);
				f.setAccessible(true);
				return f.get(instance);
			}
		} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException ex) {
			throw new ReflectionException(ex);
		}
	}

	/**
	 * Gets a member from a class, disregarding the access restrictions. If
	 * accessing a static variable, the instance may be null. If variableName
	 * contains a dot, then it recursively digs down and grabs that value. So,
	 * given the following class definitions:
	 * <pre>
	 * class A { B bObj; }
	 * class B { C cObj; }
	 * class C { String obj; }
	 * </pre> Then if clazz were A.class, and variableName were "bObj.cObj.obj",
	 * then C's String obj would be returned.
	 *
	 * @param clazz
	 * @param instance
	 * @param variableName
	 * @return
	 */
	public static Object get(Class clazz, Object instance, String variableName) throws ReflectionException {
		try {
			if (variableName.contains(".")) {
				String split[] = variableName.split("\\.");
				Object myInstance = instance;
				Class myClazz = clazz;
				for (String var : split) {
					myInstance = get(myClazz, myInstance, var);
					myClazz = myInstance.getClass();
				}
				return myInstance;
			} else {
				Field f = clazz.getDeclaredField(variableName);
				f.setAccessible(true);
				return f.get(instance);
			}
		} catch (IllegalArgumentException ex) {
			throw new ReflectionException(ex);
		} catch (IllegalAccessException ex) {
			throw new ReflectionException(ex);
		} catch (NoSuchFieldException ex) {
			throw new ReflectionException(ex);
		} catch (SecurityException ex) {
			throw new ReflectionException(ex);
		}
	}

Merge Catch [catch(IllegalArgumentException ex), catch(IllegalAccessException ex), catch(NoSuchFieldException ex), catch(SecurityException ex)] to catch(IllegalArgumentException|IllegalAccessException|NoSuchFieldException|SecurityException ex) in method public get(clazz Class, instance Object, variableName String) : Object from class com.laytonsmith.PureUtilities.Common.ReflectionUtils


	/**
	 * Sets the value of a member in a specific instance of an object,
	 * disregarding access restrictions and the final modifier.
	 *
	 * @param clazz
	 * @param instance
	 * @param variableName
	 * @param value
	 */
	public static void set(Class clazz, Object instance, String variableName, Object value) throws ReflectionException {
		try {

			if (variableName.contains(".")) {
				String split[] = variableName.split("\\.");
				Object myInstance = instance;
				Class myClazz = clazz;
				int count = 0;
				for (String var : split) {
					if (count == split.length - 1) {
						//Only the last one needs to be set
						break;
					}
					myInstance = get(myClazz, myInstance, var);
					myClazz = myInstance.getClass();
					count++;
				}
				set(myClazz, myInstance, split[split.length - 1], value);
			} else {

				Field f = clazz.getDeclaredField(variableName);
				f.setAccessible(true);

				//This is the really evil stuff here, this is what removes the final modifier.
				Field modifiersField = Field.class.getDeclaredField("modifiers");
				modifiersField.setAccessible(true);
				modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);

				f.set(instance, value);

			}
		} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException ex) {
			throw new ReflectionException(ex);
		}
	}

	/**
	 * Sets the value of a member in a specific instance of an object,
	 * disregarding access restrictions and the final modifier.
	 *
	 * @param clazz
	 * @param instance
	 * @param variableName
	 * @param value
	 */
	public static void set(Class clazz, Object instance, String variableName, Object value) throws ReflectionException {
		try {

			if (variableName.contains(".")) {
				String split[] = variableName.split("\\.");
				Object myInstance = instance;
				Class myClazz = clazz;
				int count = 0;
				for (String var : split) {
					if (count == split.length - 1) {
						//Only the last one needs to be set
						break;
					}
					myInstance = get(myClazz, myInstance, var);
					myClazz = myInstance.getClass();
					count++;
				}
				set(myClazz, myInstance, split[split.length - 1], value);
			} else {

				Field f = clazz.getDeclaredField(variableName);
				f.setAccessible(true);

				//This is the really evil stuff here, this is what removes the final modifier.
				Field modifiersField = Field.class.getDeclaredField("modifiers");
				modifiersField.setAccessible(true);
				modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);

				f.set(instance, value);

			}
		} catch (IllegalArgumentException ex) {
			throw new ReflectionException(ex);
		} catch (IllegalAccessException ex) {
			throw new ReflectionException(ex);
		} catch (NoSuchFieldException ex) {
			throw new ReflectionException(ex);
		} catch (SecurityException ex) {
			throw new ReflectionException(ex);
		}
	}

Merge Catch [catch(IllegalArgumentException ex), catch(IllegalAccessException ex), catch(NoSuchFieldException ex), catch(SecurityException ex)] to catch(IllegalArgumentException|IllegalAccessException|NoSuchFieldException|SecurityException ex) in method public set(clazz Class, instance Object, variableName String, value Object) : void from class com.laytonsmith.PureUtilities.Common.ReflectionUtils


	/**
	 * Invokes a method with the parameters specified, disregarding access
	 * restrictions, and returns the result.
	 *
	 * @param clazz
	 * @param instance
	 * @param methodName
	 * @param argTypes
	 * @param args
	 * @return
	 */
	public static Object invokeMethod(Class clazz, Object instance, String methodName, Class[] argTypes, Object[] args) throws ReflectionException {
		try {
			Method m = clazz.getDeclaredMethod(methodName, argTypes);
			m.setAccessible(true);
			return m.invoke(instance, args);
		} catch (InvocationTargetException | NoSuchMethodException | IllegalArgumentException | IllegalAccessException | SecurityException ex) {
			throw new ReflectionException(ex);
		}
	}

	/**
	 * Invokes a method with the parameters specified, disregarding access
	 * restrictions, and returns the result.
	 *
	 * @param clazz
	 * @param instance
	 * @param methodName
	 * @param argTypes
	 * @param args
	 * @return
	 */
	public static Object invokeMethod(Class clazz, Object instance, String methodName, Class[] argTypes, Object[] args) throws ReflectionException {
		try {
			Method m = clazz.getDeclaredMethod(methodName, argTypes);
			m.setAccessible(true);
			return m.invoke(instance, args);
		} catch (InvocationTargetException ex) {
			throw new ReflectionException(ex);
		} catch (NoSuchMethodException ex) {
			throw new ReflectionException(ex);
		} catch (IllegalArgumentException ex) {
			throw new ReflectionException(ex);
		} catch (IllegalAccessException ex) {
			throw new ReflectionException(ex);
		} catch (SecurityException ex) {
			throw new ReflectionException(ex);
		}
	}

Merge Catch [catch(InvocationTargetException ex), catch(NoSuchMethodException ex), catch(IllegalArgumentException ex), catch(IllegalAccessException ex), catch(SecurityException ex)] to catch(InvocationTargetException|NoSuchMethodException|IllegalArgumentException|IllegalAccessException|SecurityException ex) in method public invokeMethod(clazz Class, instance Object, methodName String, argTypes Class[], args Object[]) : Object from class com.laytonsmith.PureUtilities.Common.ReflectionUtils


	@Override
	public Set<MCTeam> getTeams() {
		Set<MCTeam> ret = new HashSet<>();
		for (Team t : s.getTeams()) {
			ret.add(new BukkitMCTeam(t));
		}
		return ret;
	}

	@Override
	public Set<MCTeam> getTeams() {
		Set<MCTeam> ret = new HashSet<MCTeam>();
		for (Team t : s.getTeams()) {
			ret.add(new BukkitMCTeam(t));
		}
		return ret;
	}

Replace Generic With Diamond HashSet<MCTeam> with HashSet<> in method public getTeams() : Set<MCTeam> from class com.laytonsmith.abstraction.bukkit.BukkitMCScoreboard


		private static Map<String, MCColor> buildColors(){
			Map<String, MCColor> map = new HashMap<>();
			map.put("AQUA", AQUA);
			map.put("BLACK", BLACK);
			map.put("BLUE", BLUE);
			map.put("FUCHSIA", FUCHSIA);
			map.put("GRAY", GRAY);
			map.put("GREY", GRAY);
			map.put("GREEN", GREEN);
			map.put("LIME", LIME);
			map.put("MAROON", MAROON);
			map.put("NAVY", NAVY);
			map.put("OLIVE", OLIVE);
			map.put("ORANGE", ORANGE);
			map.put("PURPLE", PURPLE);
			map.put("RED", RED);
			map.put("SILVER", SILVER);
			map.put("TEAL", TEAL);
			map.put("WHITE", WHITE);
			map.put("YELLOW", YELLOW);
			return Collections.unmodifiableMap(map);
		}

		private static Map<String, MCColor> buildColors(){
			Map<String, MCColor> map = new HashMap<String, MCColor>();
			map.put("AQUA", AQUA);
			map.put("BLACK", BLACK);
			map.put("BLUE", BLUE);
			map.put("FUCHSIA", FUCHSIA);
			map.put("GRAY", GRAY);
			map.put("GREY", GRAY);
			map.put("GREEN", GREEN);
			map.put("LIME", LIME);
			map.put("MAROON", MAROON);
			map.put("NAVY", NAVY);
			map.put("OLIVE", OLIVE);
			map.put("ORANGE", ORANGE);
			map.put("PURPLE", PURPLE);
			map.put("RED", RED);
			map.put("SILVER", SILVER);
			map.put("TEAL", TEAL);
			map.put("WHITE", WHITE);
			map.put("YELLOW", YELLOW);
			return Collections.unmodifiableMap(map);
		}

Replace Generic With Diamond HashMap<String,MCColor> with HashMap<> in method private buildColors() : Map<String,MCColor> from class com.laytonsmith.abstraction.MCColor.Internal


    /**
     * If it is ok to by default do a simple conversion from a CArray to a
     * Map, this method can do it for you. Likely this is not acceptable,
     * so hard-coding the conversion will be necessary.
     * @param manualObject
     * @return
     */
    public static Object DoConvert(CArray manualObject){
        Map<String, Construct> map = new HashMap<>();
        for(String key : manualObject.stringKeySet()){
            map.put(key, manualObject.get(key, Target.UNKNOWN));
        }
        return map;
    }

    /**
     * If it is ok to by default do a simple conversion from a CArray to a
     * Map, this method can do it for you. Likely this is not acceptable,
     * so hard-coding the conversion will be necessary.
     * @param manualObject
     * @return
     */
    public static Object DoConvert(CArray manualObject){
        Map<String, Construct> map = new HashMap<String, Construct>();
        for(String key : manualObject.stringKeySet()){
            map.put(key, manualObject.get(key, Target.UNKNOWN));
        }
        return map;
    }

Replace Generic With Diamond HashMap<String,Construct> with HashMap<> in method public DoConvert(manualObject CArray) : Object from class com.laytonsmith.core.events.AbstractEvent


			@Override
			public void run() {
				try {
					try (Socket s = new Socket()) {
						s.connect(new InetSocketAddress(host, port), 30000);
						remoteSocket = s;
						setStatus("Connected to remote server", true);
						setProgress(null);
						try {
							final ObjectOutputStream os = new AutoFlushObjectOutputStream(s.getOutputStream());
							final ObjectInputStream is = new ObjectInputStream(s.getInputStream());

							remoteOutput = os;
							remoteInput = is;
							// Set up our initial data
							log("Writing client version: " + PROTOCOL_VERSION);
							os.writeInt(PROTOCOL_VERSION);
							switch (is.readUTF()) {
								case "VERSION-OK":
									break;
								default:
									showError("The server does not support this client's version.");
									return;
							}
							os.writeUTF(password);
							switch (is.readUTF()) {
								case "PASSWORD-OK":
									log("Password accepted by server.");
									break;
								default:
									showError("Server rejected our password. Check the password and try again.");
									return;
							}
							os.writeUTF("SET-REMOTE-FILE");
							os.writeUTF(remoteFile);
							final MutableObject<Map<String[], String>> data = new MutableObject<>();
							final MutableObject<URI> sourceURI = new MutableObject<>();
							VirtualPersistenceNetwork vpn = null;
							connection:
							while (!Thread.currentThread().isInterrupted() && s.isConnected()) {
								String serverCommand = is.readUTF();
								switch (serverCommand) {
									case "DISCONNECT":
										break connection;
									case "FILE-OK":
										os.writeUTF("LOAD-DATA");
										reloadButton.setEnabled(false);
										break;
									case "FILE-BAD":
										showError("Remote file doesn't exist, disconnecting.");
										break;
									case "LOAD-DATA":
										int size = is.readInt();
										setStatus("Downloading data from server...", true);
										setProgress(0);
										byte[] bdata = new byte[size];
										for (int i = 0; i < size; i++) {
											bdata[i] = is.readByte();
											setProgress((int) ((((double) i) / ((double) size)) * 100));
										}
										setStatus("Processing data from server", true);
										setProgress(null);
										ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bdata));
										try {
											Map<String[], String> d = (Map<String[], String>) ois.readObject();
											data.setObject(d);
											vpn = new VirtualPersistenceNetwork() {

												Map<String, URI> sources = new HashMap<>();

												@Override
												public Map<String[], String> getAllData() throws DataSourceException {
													return data.getObject();
												}

												@Override
												public URI getKeySource(String[] key) {
													String kk = join(key);
													if (!sources.containsKey(kk)) {
														try {
															sourceURI.setObject(null);
															os.writeUTF("KEY-SOURCE");
															os.writeUTF(kk);
															synchronized (sourceURI) {
																if (sourceURI.getObject() == null) {
																	try {
																		sourceURI.wait();
																	} catch (InterruptedException ex) {
																		//
																	}
																}
															}
															URI uri = sourceURI.getObject();
															sources.put(kk, uri);
														} catch (IOException ex) {
															showError(ex.getMessage());
															log(ex);
														}
													}
													return sources.get(kk);
												}
											};
											try {
												displayData(vpn);
												setStatus("Done.", false);
											} catch (DataSourceException ex) {
												log(ex);
												showError(ex.getMessage());
											}
										} catch (ClassNotFoundException ex) {
											log(ex);
											showError(ex.getMessage());
										}
										reloadButton.setEnabled(true);
										break;
									case "KEY-SOURCE":
										try {
											URI uri = (URI) is.readObject();
											sourceURI.setObject(uri);
											synchronized (sourceURI) {
												sourceURI.notifyAll();
											}
										} catch (ClassNotFoundException ex) {
											log(ex);
										}
										break;
									case "LOAD-ERROR":
										String message = is.readUTF();
										setStatus(message, false);
										showError(message);
										reloadButton.setEnabled(true);
										break;
									default:
										showError("Server sent unrecognized command, disconnecting.");
										log("Unrecognized command: " + serverCommand);
										break connection;
								}
							}
							log("Closing connection.");
						} catch (EOFException ex) {
							log(ex);
							showError("The server closed the connection unexpectedly.");
						}
					} catch (SocketTimeoutException ex) {
						showError("Connection timed out, check your settings and try again.");
					} finally {
						setStatus("Connection to remote server closed.", false);
						remoteOutput = null;
						remoteInput = null;
						reloadButton.setEnabled(true);
					}
				} catch (IOException ex) {
					showError(ex.getMessage());
					Logger.getLogger(PNViewer.class.getName()).log(Level.SEVERE, null, ex);
				}
				remoteSocketThread = null;
			}

			@Override
			public void run() {
				try {
					Socket s = new Socket();
					try {
						s.connect(new InetSocketAddress(host, port), 30000);
						setStatus("Connected to remote server", true);
						ObjectOutputStream os = new ObjectOutputStream(s.getOutputStream());
						ObjectInputStream is = new ObjectInputStream(s.getInputStream());
						while(!Thread.currentThread().isInterrupted()){

						}
					} catch(SocketTimeoutException ex){
						showError("Connection timed out, check your settings and try again.");
					} finally {
						s.close();
					}
				} catch (IOException ex) {
					showError(ex.getMessage());
					Logger.getLogger(PNViewer.class.getName()).log(Level.SEVERE, null, ex);
				}
				remoteSocketThread = null;
			}

Try With Resources try(Socket s=new Socket()) in method public run() : void from class com.laytonsmith.tools.pnviewer.PNViewer.loadFromRemote.new Thread.new Runnable


		@Override
		public Map<String, Construct> evaluate(BindableEvent e) throws EventException {
			Map<String, Construct> map = new HashMap<>();
			map.put("time", new CInt(System.currentTimeMillis(), Target.UNKNOWN));
			return map;
		}

		@Override
		public Map<String, Construct> evaluate(BindableEvent e) throws EventException {
			Map<String, Construct> map = new HashMap<String, Construct>();
			map.put("time", new CInt(System.currentTimeMillis(), Target.UNKNOWN));
			return map;
		}

Replace Generic With Diamond HashMap<String,Construct> with HashMap<> in method public evaluate(e BindableEvent) : Map<String,Construct> from class com.laytonsmith.core.events.drivers.CmdlineEvents.cmdline_test_event


		public BukkitMCCommandTabCompleteEvent(MCCommandSender sender, Command cmd, String alias, String[] args) {
			this.comp = new ArrayList<>();
			this.sender = sender;
			this.cmd = cmd;
			this.alias = alias;
			this.args = args;
		}

		public BukkitMCCommandTabCompleteEvent(MCCommandSender sender, Command cmd, String alias, String[] args) {
			this.comp = new ArrayList<String>();
			this.sender = sender;
			this.cmd = cmd;
			this.alias = alias;
			this.args = args;
		}

Replace Generic With Diamond ArrayList<String> with ArrayList<> in method public BukkitMCCommandTabCompleteEvent(sender MCCommandSender, cmd Command, alias String, args String[]) from class com.laytonsmith.abstraction.bukkit.events.BukkitMiscEvents.BukkitMCCommandTabCompleteEvent


	public Map<MCEnchantment,Integer> enchants(CArray enchantArray, Target t) {
		Map<MCEnchantment,Integer> ret = new HashMap<>();
		for (String key : enchantArray.stringKeySet()) {
			try {
				CArray ea = (CArray) enchantArray.get(key, t);
				MCEnchantment etype = StaticLayer.GetConvertor().GetEnchantmentByName(ea.get("etype", t).val());
				int elevel = Static.getInt32(ea.get("elevel", t), t);
				if (etype == null) {
					throw new ConfigRuntimeException("Unknown enchantment type at " + key,
							ExceptionType.EnchantmentException, t);
				}
				ret.put(etype, elevel);
			} catch (ClassCastException cce) {
				throw new ConfigRuntimeException("Expected an array at index " + key, ExceptionType.FormatException, t);
			}
		}
		return ret;
	}

	public Map<MCEnchantment,Integer> enchants(CArray enchantArray, Target t) {
		Map<MCEnchantment,Integer> ret = new HashMap<MCEnchantment,Integer>();
		for (String key : enchantArray.stringKeySet()) {
			try {
				CArray ea = (CArray) enchantArray.get(key, t);
				MCEnchantment etype = StaticLayer.GetConvertor().GetEnchantmentByName(ea.get("etype", t).val());
				int elevel = Static.getInt32(ea.get("elevel", t), t);
				if (etype == null) {
					throw new ConfigRuntimeException("Unknown enchantment type at " + key,
							ExceptionType.EnchantmentException, t);
				}
				ret.put(etype, elevel);
			} catch (ClassCastException cce) {
				throw new ConfigRuntimeException("Expected an array at index " + key, ExceptionType.FormatException, t);
			}
		}
		return ret;
	}

Replace Generic With Diamond HashMap<MCEnchantment,Integer> with HashMap<> in method public enchants(enchantArray CArray, t Target) : Map<MCEnchantment,Integer> from class com.laytonsmith.core.ObjectGenerator


	public List<MCLivingEntity.MCEffect> potions(CArray ea, Target t) {
		List<MCLivingEntity.MCEffect> ret = new ArrayList<>();
		for (String key : ea.stringKeySet()) {
			if (ea.get(key, t) instanceof CArray) {
				CArray effect = (CArray) ea.get(key, t);
				int potionID = 0, strength = 0, seconds = 30;
				boolean ambient = false;
				if (effect.containsKey("id")) {
					potionID = Static.getInt32(effect.get("id", t), t);
				} else {
					throw new Exceptions.FormatException("No potion ID was given at index " + key, t);
				}
				if (effect.containsKey("strength")) {
					strength = Static.getInt32(effect.get("strength", t), t);
				}
				if (effect.containsKey("seconds")) {
					seconds = Static.getInt32(effect.get("seconds", t), t);
				}
				if (effect.containsKey("ambient")) {
					ambient = Static.getBoolean(effect.get("ambient", t));
				}
				ret.add(new MCLivingEntity.MCEffect(potionID, strength, seconds, ambient));
			} else {
				throw new Exceptions.FormatException("Expected a potion array at index" + key, t);
			}
		}
		return ret;
	}

	public List<MCLivingEntity.MCEffect> potions(CArray ea, Target t) {
		List<MCLivingEntity.MCEffect> ret = new ArrayList<MCLivingEntity.MCEffect>();
		for (String key : ea.stringKeySet()) {
			if (ea.get(key, t) instanceof CArray) {
				CArray effect = (CArray) ea.get(key, t);
				int potionID = 0, strength = 0, seconds = 30;
				boolean ambient = false;
				if (effect.containsKey("id")) {
					potionID = Static.getInt32(effect.get("id", t), t);
				} else {
					throw new Exceptions.FormatException("No potion ID was given at index " + key, t);
				}
				if (effect.containsKey("strength")) {
					strength = Static.getInt32(effect.get("strength", t), t);
				}
				if (effect.containsKey("seconds")) {
					seconds = Static.getInt32(effect.get("seconds", t), t);
				}
				if (effect.containsKey("ambient")) {
					ambient = Static.getBoolean(effect.get("ambient", t));
				}
				ret.add(new MCLivingEntity.MCEffect(potionID, strength, seconds, ambient));
			} else {
				throw new Exceptions.FormatException("Expected a potion array at index" + key, t);
			}
		}
		return ret;
	}

Replace Generic With Diamond ArrayList<MCLivingEntity.MCEffect> with ArrayList<> in method public potions(ea CArray, t Target) : List<MCLivingEntity.MCEffect> from class com.laytonsmith.core.ObjectGenerator


		@Override
		public boolean modifyEvent(String key, Construct value, BindableEvent event) {
			if (event instanceof MCPlayerEditBookEvent) {
				if (key.equalsIgnoreCase("title")) {
					MCPlayerEditBookEvent e = ((MCPlayerEditBookEvent) event);
					MCBookMeta bookMeta = e.getNewBookMeta();
					bookMeta.setTitle(value.val());
					e.setNewBookMeta(bookMeta);
					return true;
				} else if (key.equalsIgnoreCase("author")) {
					MCPlayerEditBookEvent e = ((MCPlayerEditBookEvent) event);
					MCBookMeta bookMeta = e.getNewBookMeta();
					bookMeta.setAuthor(value.val());
					e.setNewBookMeta(bookMeta);
					return true;
				} else if (key.equalsIgnoreCase("pages")) {
					CArray pageArray = Static.getArray(value, value.getTarget());
					if (pageArray.inAssociativeMode()) {
						throw new ConfigRuntimeException("The page array must not be associative.", ExceptionType.CastException, pageArray.getTarget());
					} else {
						List<String> pages = new ArrayList<>();
						for (Construct page : pageArray.asList()) {
							pages.add(page.val());
						}
						MCPlayerEditBookEvent e = ((MCPlayerEditBookEvent) event);
						MCBookMeta bookMeta = e.getNewBookMeta();
						bookMeta.setPages(pages);
						e.setNewBookMeta(bookMeta);
						return true;
					}
				} else if (key.equalsIgnoreCase("signing")) {
					((MCPlayerEditBookEvent) event).setSigning(Static.getBoolean(value));
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		}

		@Override
		public boolean modifyEvent(String key, Construct value, BindableEvent event) {
			if (event instanceof MCPlayerEditBookEvent) {
				if (key.equalsIgnoreCase("title")) {
					MCPlayerEditBookEvent e = ((MCPlayerEditBookEvent) event);
					MCBookMeta bookMeta = e.getNewBookMeta();
					bookMeta.setTitle(value.val());
					e.setNewBookMeta(bookMeta);
					return true;
				} else if (key.equalsIgnoreCase("author")) {
					MCPlayerEditBookEvent e = ((MCPlayerEditBookEvent) event);
					MCBookMeta bookMeta = e.getNewBookMeta();
					bookMeta.setAuthor(value.val());
					e.setNewBookMeta(bookMeta);
					return true;
				} else if (key.equalsIgnoreCase("pages")) {
					CArray pageArray = Static.getArray(value, value.getTarget());
					if (pageArray.inAssociativeMode()) {
						throw new ConfigRuntimeException("The page array must not be associative.", ExceptionType.CastException, pageArray.getTarget());
					} else {
						List<String> pages = new ArrayList<String>();
						for (Construct page : pageArray.asList()) {
							pages.add(page.val());
						}
						MCPlayerEditBookEvent e = ((MCPlayerEditBookEvent) event);
						MCBookMeta bookMeta = e.getNewBookMeta();
						bookMeta.setPages(pages);
						e.setNewBookMeta(bookMeta);
						return true;
					}
				} else if (key.equalsIgnoreCase("signing")) {
					((MCPlayerEditBookEvent) event).setSigning(Static.getBoolean(value));
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		}

Replace Generic With Diamond ArrayList<String> with ArrayList<> in method public modifyEvent(key String, value Construct, event BindableEvent) : boolean from class com.laytonsmith.core.events.drivers.PlayerEvents.book_edited