mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Force LF for basically everything.
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
[*.{ql,qll,qlref,dbscheme,qhelp,html,js,mjs,ts,json,yml,c,cpp,h,hpp}]
|
||||
[*]
|
||||
end_of_line = lf
|
||||
|
||||
13
.gitattributes
vendored
13
.gitattributes
vendored
@@ -16,12 +16,25 @@
|
||||
*.dbscheme eol=lf
|
||||
*.qhelp eol=lf
|
||||
*.html eol=lf
|
||||
*.htm eol=lf
|
||||
*.xhtml eol=lf
|
||||
*.xhtm eol=lf
|
||||
*.js eol=lf
|
||||
*.mjs eol=lf
|
||||
*.ts eol=lf
|
||||
*.json eol=lf
|
||||
*.yml eol=lf
|
||||
*.yaml eol=lf
|
||||
*.c eol=lf
|
||||
*.cpp eol=lf
|
||||
*.h eol=lf
|
||||
*.hpp eol=lf
|
||||
*.md eol=lf
|
||||
*.stats eol=lf
|
||||
*.xml eol=lf
|
||||
*.sh eol=lf
|
||||
*.pl eol=lf
|
||||
*.java eol=lf
|
||||
*.cs eol=lf
|
||||
*.py eol=lf
|
||||
*.lua eol=lf
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
# Improvements to C/C++ analysis
|
||||
|
||||
## General improvements
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
| *@name of query (Query ID)* | *Tags* |*Aim of the new query and whether it is enabled by default or not* |
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|----------------------------|------------------------|------------------------------------------------------------------|
|
||||
| Resource not released in destructor | Fewer false positive results | Placement new is now excluded from the query. |
|
||||
|
||||
|
||||
## Changes to QL libraries
|
||||
|
||||
* Added a hash consing library for structural comparison of expressions.
|
||||
# Improvements to C/C++ analysis
|
||||
|
||||
## General improvements
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
| *@name of query (Query ID)* | *Tags* |*Aim of the new query and whether it is enabled by default or not* |
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|----------------------------|------------------------|------------------------------------------------------------------|
|
||||
| Resource not released in destructor | Fewer false positive results | Placement new is now excluded from the query. |
|
||||
|
||||
|
||||
## Changes to QL libraries
|
||||
|
||||
* Added a hash consing library for structural comparison of expressions.
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-cpp-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.cpp.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.cpp.dbscheme"/>
|
||||
<path value="/semmlecode.cpp.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-cpp-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.cpp.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.cpp.dbscheme"/>
|
||||
<path value="/semmlecode.cpp.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
||||
@@ -1,137 +1,137 @@
|
||||
import sys
|
||||
import os.path
|
||||
import glob
|
||||
import re
|
||||
import json
|
||||
|
||||
BEGIN_TEMPLATE = re.compile(r"^/\*template\s*$")
|
||||
END_TEMPLATE = re.compile(r"^\*/\s*$")
|
||||
|
||||
def expand_template_params(args, param_arg_map):
|
||||
'''Given a list of template arguments that may reference template parameters
|
||||
of the current template, return a new list of template arguments with each
|
||||
parameter use replaced with the appropriate fully-qualified argument for
|
||||
that parameter.'''
|
||||
result = []
|
||||
for arg in args:
|
||||
if arg in param_arg_map:
|
||||
result.append(param_arg_map[arg])
|
||||
else:
|
||||
result.append(arg)
|
||||
|
||||
return result
|
||||
|
||||
def find_instantiation(module, args, templates):
|
||||
'''Given a template module and a set of template arguments, find the module
|
||||
name of the instantiation of that module with those arguments.'''
|
||||
template = templates[module]
|
||||
for instantiation in template["template_def"]["instantiations"]:
|
||||
if instantiation["args"] == args:
|
||||
return instantiation["name"]
|
||||
return None
|
||||
|
||||
def instantiate_template(template, instantiation, root, templates):
|
||||
'''Create a single instantiation of a template.'''
|
||||
template_def = template["template_def"]
|
||||
output_components = instantiation["name"].split(".")
|
||||
output_path = root
|
||||
for component in output_components:
|
||||
output_path = os.path.join(output_path, component)
|
||||
output_path = output_path + ".qll"
|
||||
with open(output_path, "w") as output:
|
||||
output.write(
|
||||
"""
|
||||
/*
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED FROM '%s'.
|
||||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
""" % (template["name"].replace(".", "/") + ".qllt")
|
||||
)
|
||||
param_arg_map = {}
|
||||
for param_index in range(len(template_def["params"])):
|
||||
param = template_def["params"][param_index]
|
||||
arg = instantiation["args"][param_index]
|
||||
output.write("private import %s as %s // Template parameter\n" % (arg, param))
|
||||
param_arg_map[param] = arg
|
||||
for import_record in template_def["imports"]:
|
||||
if "access" in import_record:
|
||||
output.write(import_record["access"] + " ")
|
||||
imported_module = find_instantiation(import_record["module"],
|
||||
expand_template_params(import_record["args"], param_arg_map), templates)
|
||||
output.write("import %s // %s<%s>\n" %
|
||||
(
|
||||
imported_module,
|
||||
import_record["module"],
|
||||
", ".join(import_record["args"])
|
||||
)
|
||||
)
|
||||
|
||||
output.writelines(template_def["body_lines"])
|
||||
|
||||
def generate_instantiations(template, root, templates):
|
||||
'''Create a .qll source file for each instantiation of the specified template.'''
|
||||
template_def = template["template_def"]
|
||||
if "instantiations" in template_def:
|
||||
for instantiation in template_def["instantiations"]:
|
||||
instantiate_template(template, instantiation, root, templates)
|
||||
|
||||
def read_template(template_path, module_name):
|
||||
'''Read a .qllt template file from template_path, using module_name as the
|
||||
fully qualified name of the module.'''
|
||||
with open(template_path) as input:
|
||||
in_template = False
|
||||
template_text = ""
|
||||
template_def = None
|
||||
body_lines = []
|
||||
for line in iter(input):
|
||||
if in_template:
|
||||
if END_TEMPLATE.match(line):
|
||||
template_def = json.loads(template_text)
|
||||
in_template = False
|
||||
else:
|
||||
template_text += line
|
||||
else:
|
||||
if BEGIN_TEMPLATE.match(line) and not template_def:
|
||||
in_template = True
|
||||
else:
|
||||
body_lines.append(line)
|
||||
|
||||
if template_def:
|
||||
template_def["body_lines"] = body_lines
|
||||
|
||||
result = { "name": module_name }
|
||||
if template_def:
|
||||
result["template_def"] = template_def
|
||||
return result
|
||||
|
||||
def module_name_from_path_impl(path):
|
||||
(head, tail) = os.path.split(path)
|
||||
if head == "":
|
||||
return tail
|
||||
else:
|
||||
return module_name_from_path(head) + "." + tail
|
||||
|
||||
def module_name_from_path(path):
|
||||
'''Compute the fully qualified name of a module from the path of its .qll[t]
|
||||
file. The path should be relative to the library root.'''
|
||||
(module_root, ext) = os.path.splitext(path)
|
||||
return module_name_from_path_impl(module_root)
|
||||
|
||||
def main():
|
||||
templates = {}
|
||||
|
||||
root = sys.argv[1]
|
||||
for template_path in glob.glob(os.path.join(root, "**\\*.qllt"), recursive = True):
|
||||
print(template_path)
|
||||
module_name = module_name_from_path(os.path.relpath(template_path, root))
|
||||
print(module_name)
|
||||
template = read_template(template_path, module_name)
|
||||
templates[template["name"]] = template
|
||||
|
||||
for name, template in templates.items():
|
||||
if "template_def" in template:
|
||||
generate_instantiations(template, root, templates)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
import sys
|
||||
import os.path
|
||||
import glob
|
||||
import re
|
||||
import json
|
||||
|
||||
BEGIN_TEMPLATE = re.compile(r"^/\*template\s*$")
|
||||
END_TEMPLATE = re.compile(r"^\*/\s*$")
|
||||
|
||||
def expand_template_params(args, param_arg_map):
|
||||
'''Given a list of template arguments that may reference template parameters
|
||||
of the current template, return a new list of template arguments with each
|
||||
parameter use replaced with the appropriate fully-qualified argument for
|
||||
that parameter.'''
|
||||
result = []
|
||||
for arg in args:
|
||||
if arg in param_arg_map:
|
||||
result.append(param_arg_map[arg])
|
||||
else:
|
||||
result.append(arg)
|
||||
|
||||
return result
|
||||
|
||||
def find_instantiation(module, args, templates):
|
||||
'''Given a template module and a set of template arguments, find the module
|
||||
name of the instantiation of that module with those arguments.'''
|
||||
template = templates[module]
|
||||
for instantiation in template["template_def"]["instantiations"]:
|
||||
if instantiation["args"] == args:
|
||||
return instantiation["name"]
|
||||
return None
|
||||
|
||||
def instantiate_template(template, instantiation, root, templates):
|
||||
'''Create a single instantiation of a template.'''
|
||||
template_def = template["template_def"]
|
||||
output_components = instantiation["name"].split(".")
|
||||
output_path = root
|
||||
for component in output_components:
|
||||
output_path = os.path.join(output_path, component)
|
||||
output_path = output_path + ".qll"
|
||||
with open(output_path, "w") as output:
|
||||
output.write(
|
||||
"""
|
||||
/*
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED FROM '%s'.
|
||||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
""" % (template["name"].replace(".", "/") + ".qllt")
|
||||
)
|
||||
param_arg_map = {}
|
||||
for param_index in range(len(template_def["params"])):
|
||||
param = template_def["params"][param_index]
|
||||
arg = instantiation["args"][param_index]
|
||||
output.write("private import %s as %s // Template parameter\n" % (arg, param))
|
||||
param_arg_map[param] = arg
|
||||
for import_record in template_def["imports"]:
|
||||
if "access" in import_record:
|
||||
output.write(import_record["access"] + " ")
|
||||
imported_module = find_instantiation(import_record["module"],
|
||||
expand_template_params(import_record["args"], param_arg_map), templates)
|
||||
output.write("import %s // %s<%s>\n" %
|
||||
(
|
||||
imported_module,
|
||||
import_record["module"],
|
||||
", ".join(import_record["args"])
|
||||
)
|
||||
)
|
||||
|
||||
output.writelines(template_def["body_lines"])
|
||||
|
||||
def generate_instantiations(template, root, templates):
|
||||
'''Create a .qll source file for each instantiation of the specified template.'''
|
||||
template_def = template["template_def"]
|
||||
if "instantiations" in template_def:
|
||||
for instantiation in template_def["instantiations"]:
|
||||
instantiate_template(template, instantiation, root, templates)
|
||||
|
||||
def read_template(template_path, module_name):
|
||||
'''Read a .qllt template file from template_path, using module_name as the
|
||||
fully qualified name of the module.'''
|
||||
with open(template_path) as input:
|
||||
in_template = False
|
||||
template_text = ""
|
||||
template_def = None
|
||||
body_lines = []
|
||||
for line in iter(input):
|
||||
if in_template:
|
||||
if END_TEMPLATE.match(line):
|
||||
template_def = json.loads(template_text)
|
||||
in_template = False
|
||||
else:
|
||||
template_text += line
|
||||
else:
|
||||
if BEGIN_TEMPLATE.match(line) and not template_def:
|
||||
in_template = True
|
||||
else:
|
||||
body_lines.append(line)
|
||||
|
||||
if template_def:
|
||||
template_def["body_lines"] = body_lines
|
||||
|
||||
result = { "name": module_name }
|
||||
if template_def:
|
||||
result["template_def"] = template_def
|
||||
return result
|
||||
|
||||
def module_name_from_path_impl(path):
|
||||
(head, tail) = os.path.split(path)
|
||||
if head == "":
|
||||
return tail
|
||||
else:
|
||||
return module_name_from_path(head) + "." + tail
|
||||
|
||||
def module_name_from_path(path):
|
||||
'''Compute the fully qualified name of a module from the path of its .qll[t]
|
||||
file. The path should be relative to the library root.'''
|
||||
(module_root, ext) = os.path.splitext(path)
|
||||
return module_name_from_path_impl(module_root)
|
||||
|
||||
def main():
|
||||
templates = {}
|
||||
|
||||
root = sys.argv[1]
|
||||
for template_path in glob.glob(os.path.join(root, "**\\*.qllt"), recursive = True):
|
||||
print(template_path)
|
||||
module_name = module_name_from_path(os.path.relpath(template_path, root))
|
||||
print(module_name)
|
||||
template = read_template(template_path, module_name)
|
||||
templates[template["name"]] = template
|
||||
|
||||
for name, template in templates.items():
|
||||
if "template_def" in template:
|
||||
generate_instantiations(template, root, templates)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-csharp-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.csharp.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.csharp.dbscheme"/>
|
||||
<path value="/semmlecode.csharp.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-csharp-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.csharp.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.csharp.dbscheme"/>
|
||||
<path value="/semmlecode.csharp.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// semmle-extractor-options: --standalone
|
||||
|
||||
using System;
|
||||
|
||||
class Cfg
|
||||
{
|
||||
void F()
|
||||
{
|
||||
var v = new InvalidType();
|
||||
Debug.Assert(v.a.b, "This is true");
|
||||
|
||||
new CounterCreationData() { CounterHelp = string.Empty, CounterType = v.Type };
|
||||
}
|
||||
}
|
||||
// semmle-extractor-options: --standalone
|
||||
|
||||
using System;
|
||||
|
||||
class Cfg
|
||||
{
|
||||
void F()
|
||||
{
|
||||
var v = new InvalidType();
|
||||
Debug.Assert(v.a.b, "This is true");
|
||||
|
||||
new CounterCreationData() { CounterHelp = string.Empty, CounterType = v.Type };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,417 +1,417 @@
|
||||
# QL Style Guide
|
||||
|
||||
## Introduction
|
||||
|
||||
This document describes how to format the QL code you contribute to this repository. It covers aspects such as layout, white-space, naming and documentation. Adhering to consistent standards makes code easier to read and maintain. Of course, these are only guidelines, and can be overridden as the need arises on a case-by-case basis. Where existing code deviates from these guidelines, prefer consistency with the surrounding code.
|
||||
|
||||
Words in *italic* are defined in the [Glossary](#glossary).
|
||||
|
||||
## Indentation
|
||||
1. *Always* use 2 spaces for indentation.
|
||||
1. *Always* indent:
|
||||
- The *body* of a module, newtype, class or predicate
|
||||
- The second and subsequent lines after you use a line break to split a long line
|
||||
- The *body* of a `from`, `where` or `select` clause where it spans multiple lines
|
||||
- The *body* of a *quantifier* that spans multiple lines
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
module Helpers {
|
||||
/** ... */
|
||||
class X ... {
|
||||
/** ... */
|
||||
int getNumberOfChildren () {
|
||||
result = count(int child |
|
||||
exists(this.getChild(child))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```ql
|
||||
from Call c, string reason
|
||||
where isDeprecated(c, reason)
|
||||
select c, "This call to '$@' is deprecated because " + reason + ".",
|
||||
c.getTarget(), c.getTarget().getName()
|
||||
```
|
||||
|
||||
## Line breaks
|
||||
1. Use UNIX line endings.
|
||||
1. Lines *must not* exceed 100 characters.
|
||||
1. Long lines *should* be split with a line break, and the following lines *must* be indented one level until the next "regular" line break.
|
||||
1. There *should* be a single blank line:
|
||||
- Between the file documentation and the first `import`
|
||||
- Before each declaration, except for the first declaration in a *body*
|
||||
- Before the `from`-`where`-`select` section in a query file
|
||||
1. *Avoid* two or more adjacent blank lines.
|
||||
1. There *must* be a new line after the *annotations* `cached`, `pragma`, `language` and `bindingset`. Other *annotations* do not have a new line.
|
||||
1. There *should not* be additional blank lines within a predicate.
|
||||
1. There *may* be a new line:
|
||||
- Immediately after the `from`, `where` or `select` keywords in a query.
|
||||
- Immediately after `if`, `then`, or `else` keywords. The `then` and `else` parts *should* be consistent.
|
||||
1. *Avoid* other line breaks in declarations, other than to break long lines.
|
||||
1. When operands of *binary operators* span two lines, the operator *should* be placed at the end of the first line.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
cached
|
||||
private int getNumberOfParameters() {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```ql
|
||||
predicate methodStats(string qualifiedName, string name,
|
||||
int numberOfParameters, int numberOfStatements, int numberOfExpressions,
|
||||
int linesOfCode, int nestingDepth, int numberOfBranches) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```ql
|
||||
from Method main
|
||||
where main.getName() = "Main"
|
||||
select main, "This is the program entry point."
|
||||
```
|
||||
|
||||
```ql
|
||||
from Method main
|
||||
where
|
||||
main.getName() = "Main" and
|
||||
main.getNumberOfParameters() = 0
|
||||
select main, "Main method has no parameters."
|
||||
```
|
||||
|
||||
```ql
|
||||
if x.isPublic()
|
||||
then result = "public"
|
||||
else result = "private"
|
||||
```
|
||||
|
||||
```ql
|
||||
if x.isPublic() then
|
||||
result = "public"
|
||||
else
|
||||
result = "private"
|
||||
```
|
||||
|
||||
```ql
|
||||
if
|
||||
x.isPublic()
|
||||
then
|
||||
result = "public"
|
||||
else
|
||||
result = "private"
|
||||
```
|
||||
|
||||
## Braces
|
||||
1. Braces follow [Stroustrup](https://en.wikipedia.org/wiki/Indentation_style#Variant:_Stroustrup) style. The opening `{` *must* be placed at the end of the preceding line.
|
||||
1. The closing `}` *must* be placed on its own line, indented to the outer level, or be on the same line as the opening `{`.
|
||||
1. Braces of empty blocks *may* be placed on a single line, with a single space separating the braces.
|
||||
1. Short predicates, not exceeding the maximum line width, *may* be placed on a single line, with a space following the opening brace and preceding the closing brace.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
class ThrowException extends ThrowExpr {
|
||||
Foo() {
|
||||
this.getTarget() instanceof ExceptionClass
|
||||
}
|
||||
|
||||
override string toString() { result = "Throw Exception" }
|
||||
}
|
||||
```
|
||||
|
||||
## Spaces
|
||||
1. There *must* be a space or line break:
|
||||
- Surrounding each `=` and `|`
|
||||
- After each `,`
|
||||
1. There *should* be a space or line break:
|
||||
- Surrounding each *binary operator*, which *must* be balanced
|
||||
- Surrounding `..` in a range
|
||||
- Exceptions to this may be made to save space or to improve readability.
|
||||
1. *Avoid* other spaces, for example:
|
||||
- After a *quantifier/aggregation* keyword
|
||||
- After the predicate name in a *call*
|
||||
- Inside brackets used for *calls*, single-line quantifiers, and parenthesised formulas
|
||||
- Surrounding a `.`
|
||||
- Inside the opening or closing `[ ]` in a range expression
|
||||
- Inside casts `a.(X)`
|
||||
1. *Avoid* multiple spaces, except for indentation, and *avoid* additional indentation to align formulas, parameters or arguments.
|
||||
1. *Do not* put whitespace on blank lines, or trailing on the end of a line.
|
||||
1. *Do not* use tabs.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
cached
|
||||
private predicate foo(Expr e, Expr p) {
|
||||
exists(int n |
|
||||
n in [0 .. 1] |
|
||||
e = p.getChild(n + 1)
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Naming
|
||||
1. Use [PascalCase](http://wiki.c2.com/?PascalCase) for:
|
||||
- `class` names
|
||||
- `module` names
|
||||
- `newtype` names
|
||||
1. Use [camelCase](https://en.wikipedia.org/wiki/Camel_case) for:
|
||||
- Predicate names
|
||||
- Variable names
|
||||
1. Newtype predicate names *should* begin with `T`.
|
||||
1. Predicates that have a result *should* be named `get...`
|
||||
1. Predicates that can return multiple results *should* be named `getA...` or `getAn...`
|
||||
1. Predicates that don't have a result or parameters *should* be named `is...` or `has...`
|
||||
1. *Avoid* underscores in names.
|
||||
1. *Avoid* short or single-letter names for classes, predicates and fields.
|
||||
1. Short or single letter names for parameters and *quantifiers* *may* be used provided that they are sufficiently clear.
|
||||
1. Use names as they are used in the target-language specification.
|
||||
1. Use American English.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
/** ... */
|
||||
predicate calls(Callable caller, Callable callee) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```ql
|
||||
/** ... */
|
||||
class Type extends ... {
|
||||
/** ... */
|
||||
string getName() { ... }
|
||||
|
||||
/** ... */
|
||||
predicate declares(Member m) { ... }
|
||||
|
||||
/** ... */
|
||||
predicate isGeneric() { ... }
|
||||
|
||||
/** ... */
|
||||
Type getTypeParameter(int n) { ... }
|
||||
|
||||
/** ... */
|
||||
Type getATypeParameter() { ... }
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
General requirements:
|
||||
|
||||
1. Documentation *must* adhere to the [QLDoc specification](https://help.semmle.com/QL/QLDocSpecification.html).
|
||||
1. Use `/** ... */` for documentation, even for single line comments.
|
||||
1. For single-line documentation, the `/**` and `*/` are written on the same line as the comment.
|
||||
1. For multi-line documentation, the `/**` and `*/` are written on separate lines. There is a `*` preceding each comment line, aligned on the first `*`.
|
||||
1. Use full sentences, with capital letters and full stops.
|
||||
1. Use American English.
|
||||
1. Documentation comments *should* be appropriate for users of the code.
|
||||
1. Documentation for maintainers of the code *must* use normal comments.
|
||||
|
||||
Documentation for specific items:
|
||||
|
||||
1. Public declarations *must* be documented.
|
||||
1. Non-public declarations *should* be documented.
|
||||
1. Declarations in query files *should* be documented.
|
||||
1. Library files (`.qll` files) *should* be have a documentation comment at the top of the file.
|
||||
1. Query files, except for tests, *must* have a QLDoc query documentation comment at the top of the file.
|
||||
1. Predicates that do not have a result *should* be documented `/** Holds if ... */`
|
||||
1. Predicates that have a result *should* be documented `/** Gets ... */`
|
||||
1. All predicate parameters *should* be referred to in the predicate documentation.
|
||||
1. Reference names, such as types and parameters, using backticks `` ` ``.
|
||||
1. Give examples of code in the target language, enclosed in ```` ``` ```` or `` ` ``.
|
||||
1. Classes *should* be documented in the singular, for example `/* An expression. */`
|
||||
1. Where a class denotes a generic concept with subclasses, list those subclasses.
|
||||
1. Declarations that are deprecated *should* be documented as `DEPRECATED: ...`
|
||||
1. Declarations that are for internal use *should* be documented as `INTERNAL: Do not use`.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
/** Provides logic for determining constant expressions. */
|
||||
```
|
||||
|
||||
```ql
|
||||
/**
|
||||
* Holds if the qualifier of this call has type `qualifierType`.
|
||||
* `isExactType` indicates whether the type is exact, that is, whether
|
||||
* the qualifier is guaranteed not to be a subtype of `qualifierType`.
|
||||
*/
|
||||
```
|
||||
```ql
|
||||
/**
|
||||
* A delegate declaration, for example
|
||||
* ```
|
||||
* delegate void Logger(string text);
|
||||
* ```
|
||||
*/
|
||||
class Delegate extends ...
|
||||
```
|
||||
|
||||
```ql
|
||||
/**
|
||||
* An element that can be called.
|
||||
*
|
||||
* Either a method (`Method`), a constructor (`Constructor`), a destructor
|
||||
* (`Destructor`), an operator (`Operator`), an accessor (`Accessor`),
|
||||
* an anonymous function (`AnonymousFunctionExpr`), or a local function
|
||||
* (`LocalFunction`).
|
||||
*/
|
||||
class Callable extends ...
|
||||
```
|
||||
|
||||
```ql
|
||||
/** DEPRECATED: Use `getAnExpr()` instead. */
|
||||
deprecated Expr getInitializer()
|
||||
```
|
||||
|
||||
```ql
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
```
|
||||
|
||||
## Formulas
|
||||
1. *Prefer* one *conjunct* per line.
|
||||
1. Write the `and` at the end of the line. This also applies in `where` clauses.
|
||||
1. *Prefer* to write the `or` keyword on its own line.
|
||||
1. The `or` keyword *may* be written at the end of a line, or within a line, provided that it has no unparenthesised `and` operands.
|
||||
1. Single-line formulas *may* be used in order to save space or add clarity, particularly in the *body* of a *quantifier/aggregation*.
|
||||
1. *Always* use brackets to clarify the precedence of:
|
||||
- `implies`
|
||||
- `if`-`then`-`else`
|
||||
1. Parenthesised formulas *can* be written:
|
||||
- Within a single line. There *should not* be an additional space following the opening parenthesis or preceding the closing parenthesis.
|
||||
- Spanning multiple lines. The opening parenthesis *should* be placed at the end of the preceding line, the body should be indented one level, and the closing bracket should be placed on a new line at the outer indentation.
|
||||
1. *Quantifiers/aggregations* *can* be written:
|
||||
- Within a single line. In this case, there is no space to the inside of the parentheses, or after the quantifier keyword.
|
||||
- Across multiple lines. In this case, type declarations are on the same line as the quantifier, the `|` *may* be at the end of the line, or *may* be on its own line, and the body of the quantifier *must* be indented one level. The closing `)` is written on a new line, at the outer indentation.
|
||||
1. `if`-`then`-`else` *can* be written:
|
||||
- On a single line
|
||||
- With the *body* after the `if`/`then`/`else` keyword
|
||||
- With the *body* indented on the next line
|
||||
- *Always* parenthesise the `else` part if it is a compound formula.
|
||||
1. The `and` and `else` keywords *may* be placed on the same line as the closing parenthesis.
|
||||
1. The `and` and `else` keywords *may* be "cuddled": `) else (`
|
||||
1. *Always* qualify *calls* to predicates of the same class with `this`.
|
||||
2. *Prefer* postfix casts `a.(Expr)` to prefix casts `(Expr)a`.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
argumentType.isImplicitlyConvertibleTo(parameterType)
|
||||
or
|
||||
argumentType instanceof NullType and
|
||||
result.getParameter(i).isOut() and
|
||||
parameterType instanceof SimpleType
|
||||
or
|
||||
reflectionOrDynamicArg(argumentType, parameterType)
|
||||
```
|
||||
|
||||
```ql
|
||||
this.getName() = "Finalize" and not exists(this.getAParameter())
|
||||
```
|
||||
|
||||
```ql
|
||||
e1.getType() instanceof BoolType and (
|
||||
b1 = true
|
||||
or
|
||||
b1 = false
|
||||
) and (
|
||||
b2 = true
|
||||
or
|
||||
b2 = false
|
||||
)
|
||||
```
|
||||
|
||||
```ql
|
||||
if e1 instanceof BitwiseOrExpr or e1 instanceof LogicalOrExpr then (
|
||||
impliesSub(e1.(BinaryOperation).getAnOperand(), e2, b1, b2) and
|
||||
b1 = false
|
||||
) else (
|
||||
e1.getType() instanceof BoolType and
|
||||
e1 = e2 and
|
||||
b1 = b2 and
|
||||
(b1 = true or b1 = false)
|
||||
)
|
||||
```
|
||||
|
||||
```ql
|
||||
(x instanceof Exception implies x.isPublic()) and y instanceof Exception
|
||||
```
|
||||
|
||||
```ql
|
||||
x instanceof Exception implies (x.isPublic() and y instanceof Exception)
|
||||
```
|
||||
|
||||
```ql
|
||||
exists(Type arg | arg = this.getAChild() | arg instanceof TypeParameter)
|
||||
```
|
||||
|
||||
```ql
|
||||
exists(Type qualifierType |
|
||||
this.hasNonExactQualifierType(qualifierType) |
|
||||
result = getANonExactQualifierSubType(qualifierType)
|
||||
)
|
||||
```
|
||||
|
||||
```ql
|
||||
methods = count(Method m | t = m.getDeclaringType() and not ilc(m))
|
||||
```
|
||||
|
||||
```ql
|
||||
if n = 0 then result = 1 else result = n * f(n - 1)
|
||||
```
|
||||
|
||||
```ql
|
||||
if n = 0
|
||||
then result = 1
|
||||
else result = n * f(n - 1)
|
||||
```
|
||||
|
||||
```ql
|
||||
if
|
||||
n = 0
|
||||
then
|
||||
result = 1
|
||||
else
|
||||
result = n * f(n - 1)
|
||||
```
|
||||
|
||||
```ql
|
||||
if exists(this.getContainingType()) then (
|
||||
result = "A nested class" and
|
||||
parentName = this.getContainingType().getFullyQualifiedName()
|
||||
) else (
|
||||
result = parentName + "." + this.getName() and
|
||||
parentName = this.getNamespace().getFullyQualifiedName()
|
||||
)
|
||||
```
|
||||
|
||||
## Glossary
|
||||
|
||||
| Phrase | Meaning |
|
||||
|-------------|----------|
|
||||
| *[annotation](https://help.semmle.com/QL/QLLanguageSpecification.html#annotations)* | An additional specifier used to modify a declaration, such as `private`, `override`, `deprecated`, `pragma`, `bindingset`, or `cached`. |
|
||||
| *body* | The text inside `{ }`, `( )`, or each section of an `if`-`then`-`else` or `from`-`where`-`select`. |
|
||||
| *binary operator* | An operator with two operands, such as comparison operators, `and`, `or`, `implies`, or arithmetic operators. |
|
||||
| *call* | A *formula* that invokes a predicate, e.g. `this.isStatic()` or `calls(a,b)`. |
|
||||
| *[conjunct](https://help.semmle.com/QL/QLLanguageSpecification.html#conjunctions)* | A formula that is an operand to an `and`. |
|
||||
| *declaration* | A class, module, predicate, field or newtype. |
|
||||
| *[disjunct](https://help.semmle.com/QL/QLLanguageSpecification.html#disjunctions)* | A formula that is an operand to an `or`. |
|
||||
| *[formula](https://help.semmle.com/QL/QLLanguageSpecification.html#formulas)* | A logical expression, such as `A = B`, a *call*, a *quantifier*, `and`, `or`, `not`, `in` or `instanceof`. |
|
||||
| *should/should not/avoid/prefer* | Adhere to this rule wherever possible, where it makes sense. |
|
||||
| *may/can* | This is a reasonable alternative, to be used with discretion. |
|
||||
| *must/always/do not* | Always adhere to this rule. |
|
||||
| *[quantifier/aggregation](https://help.semmle.com/QL/QLLanguageSpecification.html#aggregations)* | `exists`, `count`, `strictcount`, `any`, `forall`, `forex` and so on. |
|
||||
| *variable* | A parameter to a predicate, a field, a from variable, or a variable introduced by a *quantifier* or *aggregation*. |
|
||||
# QL Style Guide
|
||||
|
||||
## Introduction
|
||||
|
||||
This document describes how to format the QL code you contribute to this repository. It covers aspects such as layout, white-space, naming and documentation. Adhering to consistent standards makes code easier to read and maintain. Of course, these are only guidelines, and can be overridden as the need arises on a case-by-case basis. Where existing code deviates from these guidelines, prefer consistency with the surrounding code.
|
||||
|
||||
Words in *italic* are defined in the [Glossary](#glossary).
|
||||
|
||||
## Indentation
|
||||
1. *Always* use 2 spaces for indentation.
|
||||
1. *Always* indent:
|
||||
- The *body* of a module, newtype, class or predicate
|
||||
- The second and subsequent lines after you use a line break to split a long line
|
||||
- The *body* of a `from`, `where` or `select` clause where it spans multiple lines
|
||||
- The *body* of a *quantifier* that spans multiple lines
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
module Helpers {
|
||||
/** ... */
|
||||
class X ... {
|
||||
/** ... */
|
||||
int getNumberOfChildren () {
|
||||
result = count(int child |
|
||||
exists(this.getChild(child))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```ql
|
||||
from Call c, string reason
|
||||
where isDeprecated(c, reason)
|
||||
select c, "This call to '$@' is deprecated because " + reason + ".",
|
||||
c.getTarget(), c.getTarget().getName()
|
||||
```
|
||||
|
||||
## Line breaks
|
||||
1. Use UNIX line endings.
|
||||
1. Lines *must not* exceed 100 characters.
|
||||
1. Long lines *should* be split with a line break, and the following lines *must* be indented one level until the next "regular" line break.
|
||||
1. There *should* be a single blank line:
|
||||
- Between the file documentation and the first `import`
|
||||
- Before each declaration, except for the first declaration in a *body*
|
||||
- Before the `from`-`where`-`select` section in a query file
|
||||
1. *Avoid* two or more adjacent blank lines.
|
||||
1. There *must* be a new line after the *annotations* `cached`, `pragma`, `language` and `bindingset`. Other *annotations* do not have a new line.
|
||||
1. There *should not* be additional blank lines within a predicate.
|
||||
1. There *may* be a new line:
|
||||
- Immediately after the `from`, `where` or `select` keywords in a query.
|
||||
- Immediately after `if`, `then`, or `else` keywords. The `then` and `else` parts *should* be consistent.
|
||||
1. *Avoid* other line breaks in declarations, other than to break long lines.
|
||||
1. When operands of *binary operators* span two lines, the operator *should* be placed at the end of the first line.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
cached
|
||||
private int getNumberOfParameters() {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```ql
|
||||
predicate methodStats(string qualifiedName, string name,
|
||||
int numberOfParameters, int numberOfStatements, int numberOfExpressions,
|
||||
int linesOfCode, int nestingDepth, int numberOfBranches) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```ql
|
||||
from Method main
|
||||
where main.getName() = "Main"
|
||||
select main, "This is the program entry point."
|
||||
```
|
||||
|
||||
```ql
|
||||
from Method main
|
||||
where
|
||||
main.getName() = "Main" and
|
||||
main.getNumberOfParameters() = 0
|
||||
select main, "Main method has no parameters."
|
||||
```
|
||||
|
||||
```ql
|
||||
if x.isPublic()
|
||||
then result = "public"
|
||||
else result = "private"
|
||||
```
|
||||
|
||||
```ql
|
||||
if x.isPublic() then
|
||||
result = "public"
|
||||
else
|
||||
result = "private"
|
||||
```
|
||||
|
||||
```ql
|
||||
if
|
||||
x.isPublic()
|
||||
then
|
||||
result = "public"
|
||||
else
|
||||
result = "private"
|
||||
```
|
||||
|
||||
## Braces
|
||||
1. Braces follow [Stroustrup](https://en.wikipedia.org/wiki/Indentation_style#Variant:_Stroustrup) style. The opening `{` *must* be placed at the end of the preceding line.
|
||||
1. The closing `}` *must* be placed on its own line, indented to the outer level, or be on the same line as the opening `{`.
|
||||
1. Braces of empty blocks *may* be placed on a single line, with a single space separating the braces.
|
||||
1. Short predicates, not exceeding the maximum line width, *may* be placed on a single line, with a space following the opening brace and preceding the closing brace.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
class ThrowException extends ThrowExpr {
|
||||
Foo() {
|
||||
this.getTarget() instanceof ExceptionClass
|
||||
}
|
||||
|
||||
override string toString() { result = "Throw Exception" }
|
||||
}
|
||||
```
|
||||
|
||||
## Spaces
|
||||
1. There *must* be a space or line break:
|
||||
- Surrounding each `=` and `|`
|
||||
- After each `,`
|
||||
1. There *should* be a space or line break:
|
||||
- Surrounding each *binary operator*, which *must* be balanced
|
||||
- Surrounding `..` in a range
|
||||
- Exceptions to this may be made to save space or to improve readability.
|
||||
1. *Avoid* other spaces, for example:
|
||||
- After a *quantifier/aggregation* keyword
|
||||
- After the predicate name in a *call*
|
||||
- Inside brackets used for *calls*, single-line quantifiers, and parenthesised formulas
|
||||
- Surrounding a `.`
|
||||
- Inside the opening or closing `[ ]` in a range expression
|
||||
- Inside casts `a.(X)`
|
||||
1. *Avoid* multiple spaces, except for indentation, and *avoid* additional indentation to align formulas, parameters or arguments.
|
||||
1. *Do not* put whitespace on blank lines, or trailing on the end of a line.
|
||||
1. *Do not* use tabs.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
cached
|
||||
private predicate foo(Expr e, Expr p) {
|
||||
exists(int n |
|
||||
n in [0 .. 1] |
|
||||
e = p.getChild(n + 1)
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Naming
|
||||
1. Use [PascalCase](http://wiki.c2.com/?PascalCase) for:
|
||||
- `class` names
|
||||
- `module` names
|
||||
- `newtype` names
|
||||
1. Use [camelCase](https://en.wikipedia.org/wiki/Camel_case) for:
|
||||
- Predicate names
|
||||
- Variable names
|
||||
1. Newtype predicate names *should* begin with `T`.
|
||||
1. Predicates that have a result *should* be named `get...`
|
||||
1. Predicates that can return multiple results *should* be named `getA...` or `getAn...`
|
||||
1. Predicates that don't have a result or parameters *should* be named `is...` or `has...`
|
||||
1. *Avoid* underscores in names.
|
||||
1. *Avoid* short or single-letter names for classes, predicates and fields.
|
||||
1. Short or single letter names for parameters and *quantifiers* *may* be used provided that they are sufficiently clear.
|
||||
1. Use names as they are used in the target-language specification.
|
||||
1. Use American English.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
/** ... */
|
||||
predicate calls(Callable caller, Callable callee) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```ql
|
||||
/** ... */
|
||||
class Type extends ... {
|
||||
/** ... */
|
||||
string getName() { ... }
|
||||
|
||||
/** ... */
|
||||
predicate declares(Member m) { ... }
|
||||
|
||||
/** ... */
|
||||
predicate isGeneric() { ... }
|
||||
|
||||
/** ... */
|
||||
Type getTypeParameter(int n) { ... }
|
||||
|
||||
/** ... */
|
||||
Type getATypeParameter() { ... }
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
General requirements:
|
||||
|
||||
1. Documentation *must* adhere to the [QLDoc specification](https://help.semmle.com/QL/QLDocSpecification.html).
|
||||
1. Use `/** ... */` for documentation, even for single line comments.
|
||||
1. For single-line documentation, the `/**` and `*/` are written on the same line as the comment.
|
||||
1. For multi-line documentation, the `/**` and `*/` are written on separate lines. There is a `*` preceding each comment line, aligned on the first `*`.
|
||||
1. Use full sentences, with capital letters and full stops.
|
||||
1. Use American English.
|
||||
1. Documentation comments *should* be appropriate for users of the code.
|
||||
1. Documentation for maintainers of the code *must* use normal comments.
|
||||
|
||||
Documentation for specific items:
|
||||
|
||||
1. Public declarations *must* be documented.
|
||||
1. Non-public declarations *should* be documented.
|
||||
1. Declarations in query files *should* be documented.
|
||||
1. Library files (`.qll` files) *should* be have a documentation comment at the top of the file.
|
||||
1. Query files, except for tests, *must* have a QLDoc query documentation comment at the top of the file.
|
||||
1. Predicates that do not have a result *should* be documented `/** Holds if ... */`
|
||||
1. Predicates that have a result *should* be documented `/** Gets ... */`
|
||||
1. All predicate parameters *should* be referred to in the predicate documentation.
|
||||
1. Reference names, such as types and parameters, using backticks `` ` ``.
|
||||
1. Give examples of code in the target language, enclosed in ```` ``` ```` or `` ` ``.
|
||||
1. Classes *should* be documented in the singular, for example `/* An expression. */`
|
||||
1. Where a class denotes a generic concept with subclasses, list those subclasses.
|
||||
1. Declarations that are deprecated *should* be documented as `DEPRECATED: ...`
|
||||
1. Declarations that are for internal use *should* be documented as `INTERNAL: Do not use`.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
/** Provides logic for determining constant expressions. */
|
||||
```
|
||||
|
||||
```ql
|
||||
/**
|
||||
* Holds if the qualifier of this call has type `qualifierType`.
|
||||
* `isExactType` indicates whether the type is exact, that is, whether
|
||||
* the qualifier is guaranteed not to be a subtype of `qualifierType`.
|
||||
*/
|
||||
```
|
||||
```ql
|
||||
/**
|
||||
* A delegate declaration, for example
|
||||
* ```
|
||||
* delegate void Logger(string text);
|
||||
* ```
|
||||
*/
|
||||
class Delegate extends ...
|
||||
```
|
||||
|
||||
```ql
|
||||
/**
|
||||
* An element that can be called.
|
||||
*
|
||||
* Either a method (`Method`), a constructor (`Constructor`), a destructor
|
||||
* (`Destructor`), an operator (`Operator`), an accessor (`Accessor`),
|
||||
* an anonymous function (`AnonymousFunctionExpr`), or a local function
|
||||
* (`LocalFunction`).
|
||||
*/
|
||||
class Callable extends ...
|
||||
```
|
||||
|
||||
```ql
|
||||
/** DEPRECATED: Use `getAnExpr()` instead. */
|
||||
deprecated Expr getInitializer()
|
||||
```
|
||||
|
||||
```ql
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
```
|
||||
|
||||
## Formulas
|
||||
1. *Prefer* one *conjunct* per line.
|
||||
1. Write the `and` at the end of the line. This also applies in `where` clauses.
|
||||
1. *Prefer* to write the `or` keyword on its own line.
|
||||
1. The `or` keyword *may* be written at the end of a line, or within a line, provided that it has no unparenthesised `and` operands.
|
||||
1. Single-line formulas *may* be used in order to save space or add clarity, particularly in the *body* of a *quantifier/aggregation*.
|
||||
1. *Always* use brackets to clarify the precedence of:
|
||||
- `implies`
|
||||
- `if`-`then`-`else`
|
||||
1. Parenthesised formulas *can* be written:
|
||||
- Within a single line. There *should not* be an additional space following the opening parenthesis or preceding the closing parenthesis.
|
||||
- Spanning multiple lines. The opening parenthesis *should* be placed at the end of the preceding line, the body should be indented one level, and the closing bracket should be placed on a new line at the outer indentation.
|
||||
1. *Quantifiers/aggregations* *can* be written:
|
||||
- Within a single line. In this case, there is no space to the inside of the parentheses, or after the quantifier keyword.
|
||||
- Across multiple lines. In this case, type declarations are on the same line as the quantifier, the `|` *may* be at the end of the line, or *may* be on its own line, and the body of the quantifier *must* be indented one level. The closing `)` is written on a new line, at the outer indentation.
|
||||
1. `if`-`then`-`else` *can* be written:
|
||||
- On a single line
|
||||
- With the *body* after the `if`/`then`/`else` keyword
|
||||
- With the *body* indented on the next line
|
||||
- *Always* parenthesise the `else` part if it is a compound formula.
|
||||
1. The `and` and `else` keywords *may* be placed on the same line as the closing parenthesis.
|
||||
1. The `and` and `else` keywords *may* be "cuddled": `) else (`
|
||||
1. *Always* qualify *calls* to predicates of the same class with `this`.
|
||||
2. *Prefer* postfix casts `a.(Expr)` to prefix casts `(Expr)a`.
|
||||
|
||||
### Examples
|
||||
|
||||
```ql
|
||||
argumentType.isImplicitlyConvertibleTo(parameterType)
|
||||
or
|
||||
argumentType instanceof NullType and
|
||||
result.getParameter(i).isOut() and
|
||||
parameterType instanceof SimpleType
|
||||
or
|
||||
reflectionOrDynamicArg(argumentType, parameterType)
|
||||
```
|
||||
|
||||
```ql
|
||||
this.getName() = "Finalize" and not exists(this.getAParameter())
|
||||
```
|
||||
|
||||
```ql
|
||||
e1.getType() instanceof BoolType and (
|
||||
b1 = true
|
||||
or
|
||||
b1 = false
|
||||
) and (
|
||||
b2 = true
|
||||
or
|
||||
b2 = false
|
||||
)
|
||||
```
|
||||
|
||||
```ql
|
||||
if e1 instanceof BitwiseOrExpr or e1 instanceof LogicalOrExpr then (
|
||||
impliesSub(e1.(BinaryOperation).getAnOperand(), e2, b1, b2) and
|
||||
b1 = false
|
||||
) else (
|
||||
e1.getType() instanceof BoolType and
|
||||
e1 = e2 and
|
||||
b1 = b2 and
|
||||
(b1 = true or b1 = false)
|
||||
)
|
||||
```
|
||||
|
||||
```ql
|
||||
(x instanceof Exception implies x.isPublic()) and y instanceof Exception
|
||||
```
|
||||
|
||||
```ql
|
||||
x instanceof Exception implies (x.isPublic() and y instanceof Exception)
|
||||
```
|
||||
|
||||
```ql
|
||||
exists(Type arg | arg = this.getAChild() | arg instanceof TypeParameter)
|
||||
```
|
||||
|
||||
```ql
|
||||
exists(Type qualifierType |
|
||||
this.hasNonExactQualifierType(qualifierType) |
|
||||
result = getANonExactQualifierSubType(qualifierType)
|
||||
)
|
||||
```
|
||||
|
||||
```ql
|
||||
methods = count(Method m | t = m.getDeclaringType() and not ilc(m))
|
||||
```
|
||||
|
||||
```ql
|
||||
if n = 0 then result = 1 else result = n * f(n - 1)
|
||||
```
|
||||
|
||||
```ql
|
||||
if n = 0
|
||||
then result = 1
|
||||
else result = n * f(n - 1)
|
||||
```
|
||||
|
||||
```ql
|
||||
if
|
||||
n = 0
|
||||
then
|
||||
result = 1
|
||||
else
|
||||
result = n * f(n - 1)
|
||||
```
|
||||
|
||||
```ql
|
||||
if exists(this.getContainingType()) then (
|
||||
result = "A nested class" and
|
||||
parentName = this.getContainingType().getFullyQualifiedName()
|
||||
) else (
|
||||
result = parentName + "." + this.getName() and
|
||||
parentName = this.getNamespace().getFullyQualifiedName()
|
||||
)
|
||||
```
|
||||
|
||||
## Glossary
|
||||
|
||||
| Phrase | Meaning |
|
||||
|-------------|----------|
|
||||
| *[annotation](https://help.semmle.com/QL/QLLanguageSpecification.html#annotations)* | An additional specifier used to modify a declaration, such as `private`, `override`, `deprecated`, `pragma`, `bindingset`, or `cached`. |
|
||||
| *body* | The text inside `{ }`, `( )`, or each section of an `if`-`then`-`else` or `from`-`where`-`select`. |
|
||||
| *binary operator* | An operator with two operands, such as comparison operators, `and`, `or`, `implies`, or arithmetic operators. |
|
||||
| *call* | A *formula* that invokes a predicate, e.g. `this.isStatic()` or `calls(a,b)`. |
|
||||
| *[conjunct](https://help.semmle.com/QL/QLLanguageSpecification.html#conjunctions)* | A formula that is an operand to an `and`. |
|
||||
| *declaration* | A class, module, predicate, field or newtype. |
|
||||
| *[disjunct](https://help.semmle.com/QL/QLLanguageSpecification.html#disjunctions)* | A formula that is an operand to an `or`. |
|
||||
| *[formula](https://help.semmle.com/QL/QLLanguageSpecification.html#formulas)* | A logical expression, such as `A = B`, a *call*, a *quantifier*, `and`, `or`, `not`, `in` or `instanceof`. |
|
||||
| *should/should not/avoid/prefer* | Adhere to this rule wherever possible, where it makes sense. |
|
||||
| *may/can* | This is a reasonable alternative, to be used with discretion. |
|
||||
| *must/always/do not* | Always adhere to this rule. |
|
||||
| *[quantifier/aggregation](https://help.semmle.com/QL/QLLanguageSpecification.html#aggregations)* | `exists`, `count`, `strictcount`, `any`, `forall`, `forex` and so on. |
|
||||
| *variable* | A parameter to a predicate, a field, a from variable, or a variable introduced by a *quantifier* or *aggregation*. |
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
<!--AVOID: 'shippingService' and 'orderService' share several properties with the same values-->
|
||||
<bean id="shippingService" class="documentation.examples.spring.ShippingService">
|
||||
<property name="transactionHelper">
|
||||
<ref bean="transactionHelper"/>
|
||||
</property>
|
||||
<property name="dao">
|
||||
<ref bean="dao"/>
|
||||
</property>
|
||||
<property name="registry">
|
||||
<ref bean="basicRegistry"/>
|
||||
</property>
|
||||
|
||||
<property name="shippingProvider" value="Federal Parcel Service"/>
|
||||
</bean>
|
||||
|
||||
<bean id="orderService" class="documentation.examples.spring.OrderService">
|
||||
<property name="transactionHelper">
|
||||
<ref bean="transactionHelper"/>
|
||||
</property>
|
||||
<property name="dao">
|
||||
<ref bean="dao"/>
|
||||
</property>
|
||||
<property name="registry">
|
||||
<ref bean="basicRegistry"/>
|
||||
</property>
|
||||
|
||||
<property name="orderReference" value="8675309"/>
|
||||
<!--AVOID: 'shippingService' and 'orderService' share several properties with the same values-->
|
||||
<bean id="shippingService" class="documentation.examples.spring.ShippingService">
|
||||
<property name="transactionHelper">
|
||||
<ref bean="transactionHelper"/>
|
||||
</property>
|
||||
<property name="dao">
|
||||
<ref bean="dao"/>
|
||||
</property>
|
||||
<property name="registry">
|
||||
<ref bean="basicRegistry"/>
|
||||
</property>
|
||||
|
||||
<property name="shippingProvider" value="Federal Parcel Service"/>
|
||||
</bean>
|
||||
|
||||
<bean id="orderService" class="documentation.examples.spring.OrderService">
|
||||
<property name="transactionHelper">
|
||||
<ref bean="transactionHelper"/>
|
||||
</property>
|
||||
<property name="dao">
|
||||
<ref bean="dao"/>
|
||||
</property>
|
||||
<property name="registry">
|
||||
<ref bean="basicRegistry"/>
|
||||
</property>
|
||||
|
||||
<property name="orderReference" value="8675309"/>
|
||||
</bean>
|
||||
@@ -1,8 +1,8 @@
|
||||
<beans>
|
||||
<!--Compose configuration files by using the 'import' element.-->
|
||||
<import resource="services.xml"/>
|
||||
<import resource="resources/messageSource.xml"/>
|
||||
|
||||
<bean id="bean1" class="..."/>
|
||||
<bean id="bean2" class="..."/>
|
||||
</beans>
|
||||
<beans>
|
||||
<!--Compose configuration files by using the 'import' element.-->
|
||||
<import resource="services.xml"/>
|
||||
<import resource="resources/messageSource.xml"/>
|
||||
|
||||
<bean id="bean1" class="..."/>
|
||||
<bean id="bean2" class="..."/>
|
||||
</beans>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<beans>
|
||||
<!-- This bean is referred to, so is live. -->
|
||||
<bean id="petStore" class="org.sample.PetStoreService"/>
|
||||
<!-- This bean is never referred to, so is dead. -->
|
||||
<bean id="clinic" class="org.sample.ClinicService"/>
|
||||
</beans>
|
||||
<beans>
|
||||
<!-- This bean is referred to, so is live. -->
|
||||
<bean id="petStore" class="org.sample.PetStoreService"/>
|
||||
<!-- This bean is never referred to, so is dead. -->
|
||||
<bean id="clinic" class="org.sample.ClinicService"/>
|
||||
</beans>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
<beans>
|
||||
<bean id="baseShippingService" abstract="true">
|
||||
<property name="transactionHelper">
|
||||
<ref bean="transactionHelper"/>
|
||||
</property>
|
||||
<property name="dao">
|
||||
<ref bean="dao"/>
|
||||
</property>
|
||||
<property name="registry">
|
||||
<ref bean="basicRegistry"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="shippingService"
|
||||
class="documentation.examples.spring.ShippingService"
|
||||
parent="baseShippingService">
|
||||
<!--AVOID: This property is already defined with the same value in the parent bean.-->
|
||||
<property name="registry">
|
||||
<ref bean="basicRegistry"/>
|
||||
</property>
|
||||
<property name="shippingProvider" value="Federal Parcel Service"/>
|
||||
</bean>
|
||||
</beans>
|
||||
<beans>
|
||||
<bean id="baseShippingService" abstract="true">
|
||||
<property name="transactionHelper">
|
||||
<ref bean="transactionHelper"/>
|
||||
</property>
|
||||
<property name="dao">
|
||||
<ref bean="dao"/>
|
||||
</property>
|
||||
<property name="registry">
|
||||
<ref bean="basicRegistry"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="shippingService"
|
||||
class="documentation.examples.spring.ShippingService"
|
||||
parent="baseShippingService">
|
||||
<!--AVOID: This property is already defined with the same value in the parent bean.-->
|
||||
<property name="registry">
|
||||
<ref bean="basicRegistry"/>
|
||||
</property>
|
||||
<property name="shippingProvider" value="Federal Parcel Service"/>
|
||||
</bean>
|
||||
</beans>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<!--AVOID: Using autowiring makes it difficult to see the dependencies of the bean-->
|
||||
<bean id="autoWiredOrderService"
|
||||
class="documentation.examples.spring.OrderService"
|
||||
autowire="byName"/>
|
||||
|
||||
<!--GOOD: Explicitly specifying the properties of the bean documents its dependencies
|
||||
and makes the bean configuration easier to maintain-->
|
||||
<bean id="orderService"
|
||||
class="documentation.examples.spring.OrderService">
|
||||
<property name="DAO">
|
||||
<idref bean="dao"/>
|
||||
</property>
|
||||
<!--AVOID: Using autowiring makes it difficult to see the dependencies of the bean-->
|
||||
<bean id="autoWiredOrderService"
|
||||
class="documentation.examples.spring.OrderService"
|
||||
autowire="byName"/>
|
||||
|
||||
<!--GOOD: Explicitly specifying the properties of the bean documents its dependencies
|
||||
and makes the bean configuration easier to maintain-->
|
||||
<bean id="orderService"
|
||||
class="documentation.examples.spring.OrderService">
|
||||
<property name="DAO">
|
||||
<idref bean="dao"/>
|
||||
</property>
|
||||
</bean>
|
||||
@@ -1,13 +1,13 @@
|
||||
<!--AVOID: Using explicit constructor indices makes the bean configuration
|
||||
vulnerable to changes to the constructor-->
|
||||
<bean id="billingService1" class="documentation.examples.spring.BillingService">
|
||||
<constructor-arg index="0" value="John Doe"/>
|
||||
<constructor-arg index="1" ref="dao"/>
|
||||
</bean>
|
||||
|
||||
<!--GOOD: Using type matching makes the bean configuration more robust to changes in
|
||||
the constructor-->
|
||||
<bean id="billingService2" class="documentation.examples.spring.BillingService">
|
||||
<constructor-arg ref="dao"/>
|
||||
<constructor-arg type="java.lang.String" value="Jane Doe"/>
|
||||
<!--AVOID: Using explicit constructor indices makes the bean configuration
|
||||
vulnerable to changes to the constructor-->
|
||||
<bean id="billingService1" class="documentation.examples.spring.BillingService">
|
||||
<constructor-arg index="0" value="John Doe"/>
|
||||
<constructor-arg index="1" ref="dao"/>
|
||||
</bean>
|
||||
|
||||
<!--GOOD: Using type matching makes the bean configuration more robust to changes in
|
||||
the constructor-->
|
||||
<bean id="billingService2" class="documentation.examples.spring.BillingService">
|
||||
<constructor-arg ref="dao"/>
|
||||
<constructor-arg type="java.lang.String" value="Jane Doe"/>
|
||||
</bean>
|
||||
@@ -1,26 +1,26 @@
|
||||
<beans>
|
||||
<import resource="services.xml"/>
|
||||
|
||||
<bean id="bean1" class="..."/>
|
||||
<bean id="bean2" class="..."/>
|
||||
|
||||
<!--AVOID: Imports in the middle of a bean configuration make it difficult
|
||||
to immediately determine the dependencies of the configuration-->
|
||||
<import resource="resources/messageSource.xml"/>
|
||||
|
||||
<bean id="bean3" class="..."/>
|
||||
<bean id="bean4" class="..."/>
|
||||
</beans>
|
||||
|
||||
|
||||
<beans>
|
||||
<!--GOOD: Having the imports at the top immediately gives an idea of
|
||||
what the dependencies of the configuration are-->
|
||||
<import resource="services.xml"/>
|
||||
<import resource="resources/messageSource.xml"/>
|
||||
|
||||
<bean id="bean1" class="..."/>
|
||||
<bean id="bean2" class="..."/>
|
||||
<bean id="bean3" class="..."/>
|
||||
<bean id="bean4" class="..."/>
|
||||
</beans>
|
||||
<beans>
|
||||
<import resource="services.xml"/>
|
||||
|
||||
<bean id="bean1" class="..."/>
|
||||
<bean id="bean2" class="..."/>
|
||||
|
||||
<!--AVOID: Imports in the middle of a bean configuration make it difficult
|
||||
to immediately determine the dependencies of the configuration-->
|
||||
<import resource="resources/messageSource.xml"/>
|
||||
|
||||
<bean id="bean3" class="..."/>
|
||||
<bean id="bean4" class="..."/>
|
||||
</beans>
|
||||
|
||||
|
||||
<beans>
|
||||
<!--GOOD: Having the imports at the top immediately gives an idea of
|
||||
what the dependencies of the configuration are-->
|
||||
<import resource="services.xml"/>
|
||||
<import resource="resources/messageSource.xml"/>
|
||||
|
||||
<bean id="bean1" class="..."/>
|
||||
<bean id="bean2" class="..."/>
|
||||
<bean id="bean3" class="..."/>
|
||||
<bean id="bean4" class="..."/>
|
||||
</beans>
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
<beans>
|
||||
<!--Using a description element makes it easier for tools to pick up
|
||||
documentation of the bean configuration-->
|
||||
<description>
|
||||
This file configures the various service beans.
|
||||
</description>
|
||||
|
||||
<!--You can also put a description element in a bean-->
|
||||
<bean id="baseService" abstract="true">
|
||||
<description>
|
||||
This bean defines base properties common to the service beans
|
||||
</description>
|
||||
...
|
||||
</bean>
|
||||
|
||||
<bean id="shippingService"
|
||||
class="documentation.examples.spring.ShippingService"
|
||||
parent="baseService">
|
||||
...
|
||||
</bean>
|
||||
|
||||
<bean id="orderService"
|
||||
class="documentation.examples.spring.OrderService"
|
||||
parent="baseService">
|
||||
...
|
||||
</bean>
|
||||
<beans>
|
||||
<!--Using a description element makes it easier for tools to pick up
|
||||
documentation of the bean configuration-->
|
||||
<description>
|
||||
This file configures the various service beans.
|
||||
</description>
|
||||
|
||||
<!--You can also put a description element in a bean-->
|
||||
<bean id="baseService" abstract="true">
|
||||
<description>
|
||||
This bean defines base properties common to the service beans
|
||||
</description>
|
||||
...
|
||||
</bean>
|
||||
|
||||
<bean id="shippingService"
|
||||
class="documentation.examples.spring.ShippingService"
|
||||
parent="baseService">
|
||||
...
|
||||
</bean>
|
||||
|
||||
<bean id="orderService"
|
||||
class="documentation.examples.spring.OrderService"
|
||||
parent="baseService">
|
||||
...
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -1,16 +1,16 @@
|
||||
<!--AVOID: Using the 'name' attribute disables checking of bean references at XML parse time-->
|
||||
<bean name="dao" class="documentation.examples.spring.DAO"/>
|
||||
|
||||
<bean id="orderService" class="documentation.examples.spring.OrderService">
|
||||
<!--The XML parser cannot catch this typo-->
|
||||
<property name="dao" ref="da0"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<!--GOOD: Using the 'id' attribute enables checking of bean references at XML parse time-->
|
||||
<bean id="dao" class="documentation.examples.spring.DAO"/>
|
||||
|
||||
<bean id="orderService" class="documentation.examples.spring.OrderService">
|
||||
<!--The XML parser can catch this typo-->
|
||||
<property name="dao" ref="da0"/>
|
||||
<!--AVOID: Using the 'name' attribute disables checking of bean references at XML parse time-->
|
||||
<bean name="dao" class="documentation.examples.spring.DAO"/>
|
||||
|
||||
<bean id="orderService" class="documentation.examples.spring.OrderService">
|
||||
<!--The XML parser cannot catch this typo-->
|
||||
<property name="dao" ref="da0"/>
|
||||
</bean>
|
||||
|
||||
|
||||
<!--GOOD: Using the 'id' attribute enables checking of bean references at XML parse time-->
|
||||
<bean id="dao" class="documentation.examples.spring.DAO"/>
|
||||
|
||||
<bean id="orderService" class="documentation.examples.spring.OrderService">
|
||||
<!--The XML parser can catch this typo-->
|
||||
<property name="dao" ref="da0"/>
|
||||
</bean>
|
||||
@@ -1,17 +1,17 @@
|
||||
<beans>
|
||||
<bean id="shippingService" class="documentation.examples.spring.ShippingService">
|
||||
<!--AVOID: This form of reference cannot be checked by the XML parser-->
|
||||
<property name="dao">
|
||||
<ref bean="dao"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="orderService" class="documentation.examples.spring.OrderService">
|
||||
<!--GOOD: This form of reference allows the XML parser to find any errors at parse time-->
|
||||
<property name="dao">
|
||||
<idref local="dao"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="dao" class="documentation.examples.spring.DAO"/>
|
||||
<beans>
|
||||
<bean id="shippingService" class="documentation.examples.spring.ShippingService">
|
||||
<!--AVOID: This form of reference cannot be checked by the XML parser-->
|
||||
<property name="dao">
|
||||
<ref bean="dao"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="orderService" class="documentation.examples.spring.OrderService">
|
||||
<!--GOOD: This form of reference allows the XML parser to find any errors at parse time-->
|
||||
<property name="dao">
|
||||
<idref local="dao"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="dao" class="documentation.examples.spring.DAO"/>
|
||||
</beans>
|
||||
@@ -1,22 +1,22 @@
|
||||
// Class for bean 'chart1'
|
||||
public class WrongChartMaker {
|
||||
private AxisRenderer axisRenderer = new DefaultAxisRenderer();
|
||||
private TrendRenderer trendRenderer = new DefaultTrendRenderer();
|
||||
|
||||
public WrongChartMaker() {}
|
||||
|
||||
// Each combination of the optional parameters must be represented by a constructor.
|
||||
public WrongChartMaker(AxisRenderer customAxisRenderer) {
|
||||
this.axisRenderer = customAxisRenderer;
|
||||
}
|
||||
|
||||
public WrongChartMaker(TrendRenderer customTrendRenderer) {
|
||||
this.trendRenderer = customTrendRenderer;
|
||||
}
|
||||
|
||||
public WrongChartMaker(AxisRenderer customAxisRenderer,
|
||||
TrendRenderer customTrendRenderer) {
|
||||
this.axisRenderer = customAxisRenderer;
|
||||
this.trendRenderer = customTrendRenderer;
|
||||
}
|
||||
// Class for bean 'chart1'
|
||||
public class WrongChartMaker {
|
||||
private AxisRenderer axisRenderer = new DefaultAxisRenderer();
|
||||
private TrendRenderer trendRenderer = new DefaultTrendRenderer();
|
||||
|
||||
public WrongChartMaker() {}
|
||||
|
||||
// Each combination of the optional parameters must be represented by a constructor.
|
||||
public WrongChartMaker(AxisRenderer customAxisRenderer) {
|
||||
this.axisRenderer = customAxisRenderer;
|
||||
}
|
||||
|
||||
public WrongChartMaker(TrendRenderer customTrendRenderer) {
|
||||
this.trendRenderer = customTrendRenderer;
|
||||
}
|
||||
|
||||
public WrongChartMaker(AxisRenderer customAxisRenderer,
|
||||
TrendRenderer customTrendRenderer) {
|
||||
this.axisRenderer = customAxisRenderer;
|
||||
this.trendRenderer = customTrendRenderer;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,38 @@
|
||||
<!--AVOID: Using nested 'value' elements can make the configuration file difficult to read-->
|
||||
<bean id="serviceRegistry" class="documentation.examples.spring.ServiceRegistry">
|
||||
<constructor-arg type="java.lang.String">
|
||||
<value>main_service_registry</value>
|
||||
</constructor-arg>
|
||||
<property name="description">
|
||||
<value>Top-level registry for services</value>
|
||||
</property>
|
||||
<property name="serviceMap">
|
||||
<map>
|
||||
<entry>
|
||||
<key>
|
||||
<value>orderService</value>
|
||||
</key>
|
||||
<value>com.foo.bar.OrderService</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>
|
||||
<value>billingService</value>
|
||||
</key>
|
||||
<value>com.foo.bar.BillingService</value>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
||||
<!--GOOD: Shortcut forms (Spring 1.2) result in more concise bean definitions-->
|
||||
<bean id="serviceRegistry" class="documentation.examples.spring.ServiceRegistry">
|
||||
<constructor-arg type="java.lang.String" value="main_service_registry"/>
|
||||
<property name="description" value="Top-level registry for services"/>
|
||||
<property name="serviceMap">
|
||||
<map>
|
||||
<entry key="orderService" value="com.foo.bar.OrderService"/>
|
||||
<entry key="billingService" value="com.foo.bar.BillingService"/>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
<!--AVOID: Using nested 'value' elements can make the configuration file difficult to read-->
|
||||
<bean id="serviceRegistry" class="documentation.examples.spring.ServiceRegistry">
|
||||
<constructor-arg type="java.lang.String">
|
||||
<value>main_service_registry</value>
|
||||
</constructor-arg>
|
||||
<property name="description">
|
||||
<value>Top-level registry for services</value>
|
||||
</property>
|
||||
<property name="serviceMap">
|
||||
<map>
|
||||
<entry>
|
||||
<key>
|
||||
<value>orderService</value>
|
||||
</key>
|
||||
<value>com.foo.bar.OrderService</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>
|
||||
<value>billingService</value>
|
||||
</key>
|
||||
<value>com.foo.bar.BillingService</value>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
||||
<!--GOOD: Shortcut forms (Spring 1.2) result in more concise bean definitions-->
|
||||
<bean id="serviceRegistry" class="documentation.examples.spring.ServiceRegistry">
|
||||
<constructor-arg type="java.lang.String" value="main_service_registry"/>
|
||||
<property name="description" value="Top-level registry for services"/>
|
||||
<property name="serviceMap">
|
||||
<map>
|
||||
<entry key="orderService" value="com.foo.bar.OrderService"/>
|
||||
<entry key="billingService" value="com.foo.bar.BillingService"/>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// bean class
|
||||
public class ContentService {
|
||||
private TransactionHelper helper;
|
||||
|
||||
// This method does not match the property in the bean file.
|
||||
public void setHelper(TransactionHelper helper) {
|
||||
this.helper = helper;
|
||||
}
|
||||
}
|
||||
// bean class
|
||||
public class ContentService {
|
||||
private TransactionHelper helper;
|
||||
|
||||
// This method does not match the property in the bean file.
|
||||
public void setHelper(TransactionHelper helper) {
|
||||
this.helper = helper;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<bean id="contentService" class="documentation.examples.spring.ContentService">
|
||||
<!--BAD: The setter method in the class is 'setHelper', so this property
|
||||
does not match the setter method.-->
|
||||
<property name="transactionHelper">
|
||||
<ref bean="transactionHelper"/>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="contentService" class="documentation.examples.spring.ContentService">
|
||||
<!--BAD: The setter method in the class is 'setHelper', so this property
|
||||
does not match the setter method.-->
|
||||
<property name="transactionHelper">
|
||||
<ref bean="transactionHelper"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
public static void main(String args[]) {
|
||||
Random r = new Random();
|
||||
|
||||
// BAD: 'mayBeNegativeInt' is negative if
|
||||
// 'nextInt()' returns 'Integer.MIN_VALUE'.
|
||||
int mayBeNegativeInt = Math.abs(r.nextInt());
|
||||
|
||||
// GOOD: 'nonNegativeInt' is always a value between 0 (inclusive)
|
||||
// and Integer.MAX_VALUE (exclusive).
|
||||
int nonNegativeInt = r.nextInt(Integer.MAX_VALUE);
|
||||
|
||||
// GOOD: When 'nextInt' returns a negative number increment the returned value.
|
||||
int nextInt = r.nextInt();
|
||||
if(nextInt < 0)
|
||||
nextInt++;
|
||||
int nonNegativeInt = Math.abs(nextInt);
|
||||
}
|
||||
public static void main(String args[]) {
|
||||
Random r = new Random();
|
||||
|
||||
// BAD: 'mayBeNegativeInt' is negative if
|
||||
// 'nextInt()' returns 'Integer.MIN_VALUE'.
|
||||
int mayBeNegativeInt = Math.abs(r.nextInt());
|
||||
|
||||
// GOOD: 'nonNegativeInt' is always a value between 0 (inclusive)
|
||||
// and Integer.MAX_VALUE (exclusive).
|
||||
int nonNegativeInt = r.nextInt(Integer.MAX_VALUE);
|
||||
|
||||
// GOOD: When 'nextInt' returns a negative number increment the returned value.
|
||||
int nextInt = r.nextInt();
|
||||
if(nextInt < 0)
|
||||
nextInt++;
|
||||
int nonNegativeInt = Math.abs(nextInt);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
public static void main(String args[]) {
|
||||
// BAD: A new 'Random' object is created every time
|
||||
// a pseudo-random integer is required.
|
||||
int notReallyRandom = new Random().nextInt();
|
||||
int notReallyRandom2 = new Random().nextInt();
|
||||
|
||||
// GOOD: The same 'Random' object is used to generate
|
||||
// two pseudo-random integers.
|
||||
Random r = new Random();
|
||||
int random1 = r.nextInt();
|
||||
int random2 = r.nextInt();
|
||||
public static void main(String args[]) {
|
||||
// BAD: A new 'Random' object is created every time
|
||||
// a pseudo-random integer is required.
|
||||
int notReallyRandom = new Random().nextInt();
|
||||
int notReallyRandom2 = new Random().nextInt();
|
||||
|
||||
// GOOD: The same 'Random' object is used to generate
|
||||
// two pseudo-random integers.
|
||||
Random r = new Random();
|
||||
int random1 = r.nextInt();
|
||||
int random2 = r.nextInt();
|
||||
}
|
||||
@@ -1,30 +1,30 @@
|
||||
class LocalCache {
|
||||
private Collection<NativeResource> localResources;
|
||||
|
||||
//...
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
for (NativeResource r : localResources) {
|
||||
r.dispose();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class WrongCache extends LocalCache {
|
||||
//...
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
// BAD: Empty 'finalize', which does not call 'super.finalize'.
|
||||
// Native resources in LocalCache are not disposed of.
|
||||
}
|
||||
}
|
||||
|
||||
class RightCache extends LocalCache {
|
||||
//...
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
// GOOD: 'finalize' calls 'super.finalize'.
|
||||
// Native resources in LocalCache are disposed of.
|
||||
super.finalize();
|
||||
}
|
||||
class LocalCache {
|
||||
private Collection<NativeResource> localResources;
|
||||
|
||||
//...
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
for (NativeResource r : localResources) {
|
||||
r.dispose();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class WrongCache extends LocalCache {
|
||||
//...
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
// BAD: Empty 'finalize', which does not call 'super.finalize'.
|
||||
// Native resources in LocalCache are not disposed of.
|
||||
}
|
||||
}
|
||||
|
||||
class RightCache extends LocalCache {
|
||||
//...
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
// GOOD: 'finalize' calls 'super.finalize'.
|
||||
// Native resources in LocalCache are disposed of.
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
public class BadSuiteMethod extends TestCase {
|
||||
// BAD: JUnit 3.8 does not detect the following method as a 'suite' method.
|
||||
// The method should be public, static, and return 'junit.framework.Test'
|
||||
// or one of its subtypes.
|
||||
static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
suite.addTest(new MyTests("testEquals"));
|
||||
suite.addTest(new MyTests("testNotEquals"));
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
|
||||
public class CorrectSuiteMethod extends TestCase {
|
||||
// GOOD: JUnit 3.8 correctly detects the following method as a 'suite' method.
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
suite.addTest(new MyTests("testEquals"));
|
||||
suite.addTest(new MyTests("testNotEquals"));
|
||||
return suite;
|
||||
}
|
||||
public class BadSuiteMethod extends TestCase {
|
||||
// BAD: JUnit 3.8 does not detect the following method as a 'suite' method.
|
||||
// The method should be public, static, and return 'junit.framework.Test'
|
||||
// or one of its subtypes.
|
||||
static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
suite.addTest(new MyTests("testEquals"));
|
||||
suite.addTest(new MyTests("testNotEquals"));
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
|
||||
public class CorrectSuiteMethod extends TestCase {
|
||||
// GOOD: JUnit 3.8 correctly detects the following method as a 'suite' method.
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
suite.addTest(new MyTests("testEquals"));
|
||||
suite.addTest(new MyTests("testNotEquals"));
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,65 @@
|
||||
// Abstract class that initializes then shuts down the
|
||||
// framework after each set of tests
|
||||
abstract class FrameworkTestCase extends TestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
Framework.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
Framework.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
// The following classes extend 'FrameworkTestCase' to reuse the
|
||||
// 'setUp' and 'tearDown' methods of the framework.
|
||||
|
||||
public class TearDownNoSuper extends FrameworkTestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testFramework() {
|
||||
//...
|
||||
}
|
||||
|
||||
public void testFramework2() {
|
||||
//...
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
// BAD: Does not call 'super.tearDown'. May cause later tests to fail
|
||||
// when they try to re-initialize an already initialized framework.
|
||||
// Even if the framework allows re-initialization, it may maintain the
|
||||
// internal state, which could affect the results of succeeding tests.
|
||||
System.out.println("Tests complete");
|
||||
}
|
||||
}
|
||||
|
||||
public class TearDownSuper extends FrameworkTestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testFramework() {
|
||||
//...
|
||||
}
|
||||
|
||||
public void testFramework2() {
|
||||
//...
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
// GOOD: Correctly calls 'super.tearDown' to shut down the
|
||||
// framework.
|
||||
System.out.println("Tests complete");
|
||||
super.tearDown();
|
||||
}
|
||||
// Abstract class that initializes then shuts down the
|
||||
// framework after each set of tests
|
||||
abstract class FrameworkTestCase extends TestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
Framework.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
Framework.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
// The following classes extend 'FrameworkTestCase' to reuse the
|
||||
// 'setUp' and 'tearDown' methods of the framework.
|
||||
|
||||
public class TearDownNoSuper extends FrameworkTestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testFramework() {
|
||||
//...
|
||||
}
|
||||
|
||||
public void testFramework2() {
|
||||
//...
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
// BAD: Does not call 'super.tearDown'. May cause later tests to fail
|
||||
// when they try to re-initialize an already initialized framework.
|
||||
// Even if the framework allows re-initialization, it may maintain the
|
||||
// internal state, which could affect the results of succeeding tests.
|
||||
System.out.println("Tests complete");
|
||||
}
|
||||
}
|
||||
|
||||
public class TearDownSuper extends FrameworkTestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public void testFramework() {
|
||||
//...
|
||||
}
|
||||
|
||||
public void testFramework2() {
|
||||
//...
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
// GOOD: Correctly calls 'super.tearDown' to shut down the
|
||||
// framework.
|
||||
System.out.println("Tests complete");
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,28 @@
|
||||
// BAD: This test case class does not have any valid JUnit 3.8 test methods.
|
||||
public class TestCaseNoTests38 extends TestCase {
|
||||
// This is not a test case because it does not start with 'test'.
|
||||
public void simpleTest() {
|
||||
//...
|
||||
}
|
||||
|
||||
// This is not a test case because it takes two parameters.
|
||||
public void testNotEquals(int i, int j) {
|
||||
assertEquals(i != j, true);
|
||||
}
|
||||
|
||||
// This is recognized as a test, but causes JUnit to fail
|
||||
// when run because it is not public.
|
||||
void testEquals() {
|
||||
//...
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: This test case class correctly declares test methods.
|
||||
public class MyTests extends TestCase {
|
||||
public void testEquals() {
|
||||
assertEquals(1, 1);
|
||||
}
|
||||
public void testNotEquals() {
|
||||
assertFalse(1 == 2);
|
||||
}
|
||||
// BAD: This test case class does not have any valid JUnit 3.8 test methods.
|
||||
public class TestCaseNoTests38 extends TestCase {
|
||||
// This is not a test case because it does not start with 'test'.
|
||||
public void simpleTest() {
|
||||
//...
|
||||
}
|
||||
|
||||
// This is not a test case because it takes two parameters.
|
||||
public void testNotEquals(int i, int j) {
|
||||
assertEquals(i != j, true);
|
||||
}
|
||||
|
||||
// This is recognized as a test, but causes JUnit to fail
|
||||
// when run because it is not public.
|
||||
void testEquals() {
|
||||
//...
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: This test case class correctly declares test methods.
|
||||
public class MyTests extends TestCase {
|
||||
public void testEquals() {
|
||||
assertEquals(1, 1);
|
||||
}
|
||||
public void testNotEquals() {
|
||||
assertFalse(1 == 2);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
public static void main(String args[]) {
|
||||
String phrase = "I miss my home in Mississippi.";
|
||||
|
||||
// AVOID: Calling 'toLowerCase()' or 'toUpperCase()'
|
||||
// produces different results depending on what the default locale is.
|
||||
System.out.println(phrase.toUpperCase());
|
||||
System.out.println(phrase.toLowerCase());
|
||||
|
||||
// GOOD: Explicitly setting the locale when calling 'toLowerCase()' or
|
||||
// 'toUpperCase()' ensures that the resulting string is
|
||||
// English, regardless of the default locale.
|
||||
System.out.println(phrase.toLowerCase(Locale.ENGLISH));
|
||||
System.out.println(phrase.toUpperCase(Locale.ENGLISH));
|
||||
public static void main(String args[]) {
|
||||
String phrase = "I miss my home in Mississippi.";
|
||||
|
||||
// AVOID: Calling 'toLowerCase()' or 'toUpperCase()'
|
||||
// produces different results depending on what the default locale is.
|
||||
System.out.println(phrase.toUpperCase());
|
||||
System.out.println(phrase.toLowerCase());
|
||||
|
||||
// GOOD: Explicitly setting the locale when calling 'toLowerCase()' or
|
||||
// 'toUpperCase()' ensures that the resulting string is
|
||||
// English, regardless of the default locale.
|
||||
System.out.println(phrase.toLowerCase(Locale.ENGLISH));
|
||||
System.out.println(phrase.toUpperCase(Locale.ENGLISH));
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
class WrongNote implements Serializable {
|
||||
// BAD: serialVersionUID must be static, final, and 'long'
|
||||
private static final int serialVersionUID = 1;
|
||||
|
||||
//...
|
||||
}
|
||||
|
||||
class Note implements Serializable {
|
||||
// GOOD: serialVersionUID is of the correct type
|
||||
private static final long serialVersionUID = 1L;
|
||||
class WrongNote implements Serializable {
|
||||
// BAD: serialVersionUID must be static, final, and 'long'
|
||||
private static final int serialVersionUID = 1;
|
||||
|
||||
//...
|
||||
}
|
||||
|
||||
class Note implements Serializable {
|
||||
// GOOD: serialVersionUID is of the correct type
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
@@ -1,25 +1,25 @@
|
||||
class WrongNetRequest implements Serializable {
|
||||
// BAD: Does not match the exact signature required for a custom
|
||||
// deserialization protocol. Will not be called during deserialization.
|
||||
void readObject(ObjectInputStream in) {
|
||||
//...
|
||||
}
|
||||
|
||||
// BAD: Does not match the exact signature required for a custom
|
||||
// serialization protocol. Will not be called during serialization.
|
||||
protected void writeObject(ObjectOutputStream out) {
|
||||
//...
|
||||
}
|
||||
}
|
||||
|
||||
class NetRequest implements Serializable {
|
||||
// GOOD: Signature for a custom deserialization implementation.
|
||||
private void readObject(ObjectInputStream in) {
|
||||
//...
|
||||
}
|
||||
|
||||
// GOOD: Signature for a custom serialization implementation.
|
||||
private void writeObject(ObjectOutputStream out) {
|
||||
//...
|
||||
}
|
||||
class WrongNetRequest implements Serializable {
|
||||
// BAD: Does not match the exact signature required for a custom
|
||||
// deserialization protocol. Will not be called during deserialization.
|
||||
void readObject(ObjectInputStream in) {
|
||||
//...
|
||||
}
|
||||
|
||||
// BAD: Does not match the exact signature required for a custom
|
||||
// serialization protocol. Will not be called during serialization.
|
||||
protected void writeObject(ObjectOutputStream out) {
|
||||
//...
|
||||
}
|
||||
}
|
||||
|
||||
class NetRequest implements Serializable {
|
||||
// GOOD: Signature for a custom deserialization implementation.
|
||||
private void readObject(ObjectInputStream in) {
|
||||
//...
|
||||
}
|
||||
|
||||
// GOOD: Signature for a custom serialization implementation.
|
||||
private void writeObject(ObjectOutputStream out) {
|
||||
//...
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,37 @@
|
||||
class WrongMemo implements Externalizable {
|
||||
private String memo;
|
||||
|
||||
// BAD: No public no-argument constructor is defined. Deserializing this object
|
||||
// causes an 'InvalidClassException'.
|
||||
|
||||
public WrongMemo(String memo) {
|
||||
this.memo = memo;
|
||||
}
|
||||
|
||||
public void writeExternal(ObjectOutput arg0) throws IOException {
|
||||
//...
|
||||
}
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
//...
|
||||
}
|
||||
}
|
||||
|
||||
class Memo implements Externalizable {
|
||||
private String memo;
|
||||
|
||||
// GOOD: Declare a public no-argument constructor, which is used by the
|
||||
// serialization framework when the object is deserialized.
|
||||
public Memo() {
|
||||
}
|
||||
|
||||
public Memo(String memo) {
|
||||
this.memo = memo;
|
||||
}
|
||||
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
//...
|
||||
}
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
//...
|
||||
}
|
||||
class WrongMemo implements Externalizable {
|
||||
private String memo;
|
||||
|
||||
// BAD: No public no-argument constructor is defined. Deserializing this object
|
||||
// causes an 'InvalidClassException'.
|
||||
|
||||
public WrongMemo(String memo) {
|
||||
this.memo = memo;
|
||||
}
|
||||
|
||||
public void writeExternal(ObjectOutput arg0) throws IOException {
|
||||
//...
|
||||
}
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
//...
|
||||
}
|
||||
}
|
||||
|
||||
class Memo implements Externalizable {
|
||||
private String memo;
|
||||
|
||||
// GOOD: Declare a public no-argument constructor, which is used by the
|
||||
// serialization framework when the object is deserialized.
|
||||
public Memo() {
|
||||
}
|
||||
|
||||
public Memo(String memo) {
|
||||
this.memo = memo;
|
||||
}
|
||||
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
//...
|
||||
}
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
//...
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,42 @@
|
||||
class WrongItem {
|
||||
private String name;
|
||||
|
||||
// BAD: This class does not have a no-argument constructor, and throws an
|
||||
// 'InvalidClassException' at runtime.
|
||||
|
||||
public WrongItem(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
class WrongSubItem extends WrongItem implements Serializable {
|
||||
public WrongSubItem() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public WrongSubItem(String name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
|
||||
class Item {
|
||||
private String name;
|
||||
|
||||
// GOOD: This class declares a no-argument constructor, which allows serializable
|
||||
// subclasses to be deserialized without error.
|
||||
public Item() {}
|
||||
|
||||
public Item(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
class SubItem extends Item implements Serializable {
|
||||
public SubItem() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public SubItem(String name) {
|
||||
super(name);
|
||||
}
|
||||
class WrongItem {
|
||||
private String name;
|
||||
|
||||
// BAD: This class does not have a no-argument constructor, and throws an
|
||||
// 'InvalidClassException' at runtime.
|
||||
|
||||
public WrongItem(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
class WrongSubItem extends WrongItem implements Serializable {
|
||||
public WrongSubItem() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public WrongSubItem(String name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
|
||||
class Item {
|
||||
private String name;
|
||||
|
||||
// GOOD: This class declares a no-argument constructor, which allows serializable
|
||||
// subclasses to be deserialized without error.
|
||||
public Item() {}
|
||||
|
||||
public Item(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
class SubItem extends Item implements Serializable {
|
||||
public SubItem() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public SubItem(String name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
// BAD: This is not serializable, and throws a 'java.io.NotSerializableException'
|
||||
// when used in a serializable sorted collection.
|
||||
class WrongComparator implements Comparator<String> {
|
||||
public int compare(String o1, String o2) {
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: This is serializable, and can be used in collections that are meant to be serialized.
|
||||
class StringComparator implements Comparator<String>, Serializable {
|
||||
private static final long serialVersionUID = -5972458403679726498L;
|
||||
|
||||
public int compare(String arg0, String arg1) {
|
||||
return arg0.compareTo(arg1);
|
||||
}
|
||||
// BAD: This is not serializable, and throws a 'java.io.NotSerializableException'
|
||||
// when used in a serializable sorted collection.
|
||||
class WrongComparator implements Comparator<String> {
|
||||
public int compare(String o1, String o2) {
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: This is serializable, and can be used in collections that are meant to be serialized.
|
||||
class StringComparator implements Comparator<String>, Serializable {
|
||||
private static final long serialVersionUID = -5972458403679726498L;
|
||||
|
||||
public int compare(String arg0, String arg1) {
|
||||
return arg0.compareTo(arg1);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
class DerivedFactors { // Class that contains derived values computed from entries in a
|
||||
private Number efficiency; // performance record
|
||||
private Number costPerItem;
|
||||
private Number profitPerItem;
|
||||
...
|
||||
}
|
||||
|
||||
class WrongPerformanceRecord implements Serializable {
|
||||
private String unitId;
|
||||
private Number dailyThroughput;
|
||||
private Number dailyCost;
|
||||
private DerivedFactors factors; // BAD: 'DerivedFactors' is not serializable
|
||||
// but is in a serializable class. This
|
||||
// causes a 'java.io.NotSerializableException'
|
||||
// when 'WrongPerformanceRecord' is serialized.
|
||||
...
|
||||
}
|
||||
|
||||
class PerformanceRecord implements Serializable {
|
||||
private String unitId;
|
||||
private Number dailyThroughput;
|
||||
private Number dailyCost;
|
||||
transient private DerivedFactors factors; // GOOD: 'DerivedFactors' is declared
|
||||
// 'transient' so it does not contribute to the
|
||||
// serializable state of 'PerformanceRecord'.
|
||||
...
|
||||
}
|
||||
class DerivedFactors { // Class that contains derived values computed from entries in a
|
||||
private Number efficiency; // performance record
|
||||
private Number costPerItem;
|
||||
private Number profitPerItem;
|
||||
...
|
||||
}
|
||||
|
||||
class WrongPerformanceRecord implements Serializable {
|
||||
private String unitId;
|
||||
private Number dailyThroughput;
|
||||
private Number dailyCost;
|
||||
private DerivedFactors factors; // BAD: 'DerivedFactors' is not serializable
|
||||
// but is in a serializable class. This
|
||||
// causes a 'java.io.NotSerializableException'
|
||||
// when 'WrongPerformanceRecord' is serialized.
|
||||
...
|
||||
}
|
||||
|
||||
class PerformanceRecord implements Serializable {
|
||||
private String unitId;
|
||||
private Number dailyThroughput;
|
||||
private Number dailyCost;
|
||||
transient private DerivedFactors factors; // GOOD: 'DerivedFactors' is declared
|
||||
// 'transient' so it does not contribute to the
|
||||
// serializable state of 'PerformanceRecord'.
|
||||
...
|
||||
}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
class WrongPair<L, R> implements Serializable{
|
||||
private final L left; // BAD
|
||||
private final R right; // BAD: L and R are not guaranteed to be serializable
|
||||
|
||||
public WrongPair(L left, R right){ ... }
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
class Pair<L extends Serializable, R extends Serializable> implements Serializable{
|
||||
private final L left; // GOOD: L and R must implement Serializable
|
||||
private final R right;
|
||||
|
||||
public Pair(L left, R right){ ... }
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
class WrongEvent implements Serializable{
|
||||
private Object eventData; // BAD: Type is too general.
|
||||
|
||||
public WrongEvent(Object eventData){ ... }
|
||||
}
|
||||
|
||||
class Event implements Serializable{
|
||||
private Serializable eventData; // GOOD: Force the user to supply only serializable data
|
||||
|
||||
public Event(Serializable eventData){ ... }
|
||||
}
|
||||
class WrongPair<L, R> implements Serializable{
|
||||
private final L left; // BAD
|
||||
private final R right; // BAD: L and R are not guaranteed to be serializable
|
||||
|
||||
public WrongPair(L left, R right){ ... }
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
class Pair<L extends Serializable, R extends Serializable> implements Serializable{
|
||||
private final L left; // GOOD: L and R must implement Serializable
|
||||
private final R right;
|
||||
|
||||
public Pair(L left, R right){ ... }
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
class WrongEvent implements Serializable{
|
||||
private Object eventData; // BAD: Type is too general.
|
||||
|
||||
public WrongEvent(Object eventData){ ... }
|
||||
}
|
||||
|
||||
class Event implements Serializable{
|
||||
private Serializable eventData; // GOOD: Force the user to supply only serializable data
|
||||
|
||||
public Event(Serializable eventData){ ... }
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
class NonSerializableServer {
|
||||
|
||||
// BAD: The following class is serializable, but the enclosing class
|
||||
// 'NonSerializableServer' is not. Serializing an instance of 'WrongSession'
|
||||
// causes a 'java.io.NotSerializableException'.
|
||||
class WrongSession implements Serializable {
|
||||
private static final long serialVersionUID = 8970783971992397218L;
|
||||
private int id;
|
||||
private String user;
|
||||
|
||||
WrongSession(int id, String user) { /*...*/ }
|
||||
}
|
||||
|
||||
public WrongSession getNewSession(String user) {
|
||||
return new WrongSession(newId(), user);
|
||||
}
|
||||
}
|
||||
|
||||
class Server {
|
||||
|
||||
// GOOD: The following class can be correctly serialized because it is static.
|
||||
static class Session implements Serializable {
|
||||
private static final long serialVersionUID = 1065454318648105638L;
|
||||
private int id;
|
||||
private String user;
|
||||
|
||||
Session(int id, String user) { /*...*/ }
|
||||
}
|
||||
|
||||
public Session getNewSession(String user) {
|
||||
return new Session(newId(), user);
|
||||
}
|
||||
class NonSerializableServer {
|
||||
|
||||
// BAD: The following class is serializable, but the enclosing class
|
||||
// 'NonSerializableServer' is not. Serializing an instance of 'WrongSession'
|
||||
// causes a 'java.io.NotSerializableException'.
|
||||
class WrongSession implements Serializable {
|
||||
private static final long serialVersionUID = 8970783971992397218L;
|
||||
private int id;
|
||||
private String user;
|
||||
|
||||
WrongSession(int id, String user) { /*...*/ }
|
||||
}
|
||||
|
||||
public WrongSession getNewSession(String user) {
|
||||
return new WrongSession(newId(), user);
|
||||
}
|
||||
}
|
||||
|
||||
class Server {
|
||||
|
||||
// GOOD: The following class can be correctly serialized because it is static.
|
||||
static class Session implements Serializable {
|
||||
private static final long serialVersionUID = 1065454318648105638L;
|
||||
private int id;
|
||||
private String user;
|
||||
|
||||
Session(int id, String user) { /*...*/ }
|
||||
}
|
||||
|
||||
public Session getNewSession(String user) {
|
||||
return new Session(newId(), user);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,40 @@
|
||||
class FalseSingleton implements Serializable {
|
||||
private static final long serialVersionUID = -7480651116825504381L;
|
||||
private static FalseSingleton instance;
|
||||
|
||||
private FalseSingleton() {}
|
||||
|
||||
public static FalseSingleton getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new FalseSingleton();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// BAD: Signature of 'readResolve' does not match the exact signature that is expected
|
||||
// (that is, it does not return 'java.lang.Object').
|
||||
public FalseSingleton readResolve() throws ObjectStreamException {
|
||||
return FalseSingleton.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
class Singleton implements Serializable {
|
||||
private static final long serialVersionUID = -7480651116825504381L;
|
||||
private static Singleton instance;
|
||||
|
||||
private Singleton() {}
|
||||
|
||||
public static Singleton getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Singleton();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// GOOD: Signature of 'readResolve' matches the exact signature that is expected.
|
||||
// It replaces the singleton that is read from a stream with an instance of 'Singleton',
|
||||
// instead of creating a new singleton.
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return Singleton.getInstance();
|
||||
}
|
||||
class FalseSingleton implements Serializable {
|
||||
private static final long serialVersionUID = -7480651116825504381L;
|
||||
private static FalseSingleton instance;
|
||||
|
||||
private FalseSingleton() {}
|
||||
|
||||
public static FalseSingleton getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new FalseSingleton();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// BAD: Signature of 'readResolve' does not match the exact signature that is expected
|
||||
// (that is, it does not return 'java.lang.Object').
|
||||
public FalseSingleton readResolve() throws ObjectStreamException {
|
||||
return FalseSingleton.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
class Singleton implements Serializable {
|
||||
private static final long serialVersionUID = -7480651116825504381L;
|
||||
private static Singleton instance;
|
||||
|
||||
private Singleton() {}
|
||||
|
||||
public static Singleton getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Singleton();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// GOOD: Signature of 'readResolve' matches the exact signature that is expected.
|
||||
// It replaces the singleton that is read from a stream with an instance of 'Singleton',
|
||||
// instead of creating a new singleton.
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return Singleton.getInstance();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
class State {
|
||||
// The 'transient' modifier has no effect here because
|
||||
// the 'State' class does not implement 'Serializable'.
|
||||
private transient int[] stateData;
|
||||
}
|
||||
|
||||
class PersistentState implements Serializable {
|
||||
private int[] stateData;
|
||||
// The 'transient' modifier indicates that this field is not part of
|
||||
// the persistent state and should therefore not be serialized.
|
||||
private transient int[] cachedComputedData;
|
||||
class State {
|
||||
// The 'transient' modifier has no effect here because
|
||||
// the 'State' class does not implement 'Serializable'.
|
||||
private transient int[] stateData;
|
||||
}
|
||||
|
||||
class PersistentState implements Serializable {
|
||||
private int[] stateData;
|
||||
// The 'transient' modifier indicates that this field is not part of
|
||||
// the persistent state and should therefore not be serialized.
|
||||
private transient int[] cachedComputedData;
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
class FinalizedClass {
|
||||
Object o = new Object();
|
||||
String s = "abcdefg";
|
||||
Integer i = Integer.valueOf(2);
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
//No need to nullify fields
|
||||
this.o = null;
|
||||
this.s = null;
|
||||
this.i = null;
|
||||
}
|
||||
class FinalizedClass {
|
||||
Object o = new Object();
|
||||
String s = "abcdefg";
|
||||
Integer i = Integer.valueOf(2);
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
//No need to nullify fields
|
||||
this.o = null;
|
||||
this.s = null;
|
||||
this.i = null;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
synchronized void waitIfAutoSyncScheduled() {
|
||||
try {
|
||||
while (isAutoSyncScheduled) {
|
||||
this.wait(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// Expected exception. The file cannot be synchronized yet.
|
||||
}
|
||||
synchronized void waitIfAutoSyncScheduled() {
|
||||
try {
|
||||
while (isAutoSyncScheduled) {
|
||||
this.wait(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// Expected exception. The file cannot be synchronized yet.
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
// Exception is passed to 'ignore' method with a comment
|
||||
synchronized void waitIfAutoSyncScheduled() {
|
||||
try {
|
||||
while (isAutoSyncScheduled) {
|
||||
this.wait(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Exceptions.ignore(e, "Expected exception. The file cannot be synchronized yet.");
|
||||
}
|
||||
// Exception is passed to 'ignore' method with a comment
|
||||
synchronized void waitIfAutoSyncScheduled() {
|
||||
try {
|
||||
while (isAutoSyncScheduled) {
|
||||
this.wait(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Exceptions.ignore(e, "Expected exception. The file cannot be synchronized yet.");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// 'ignore' method. This method does nothing, but can be called
|
||||
// to document the reason why the exception can be ignored.
|
||||
public static void ignore(Throwable e, String message) {
|
||||
|
||||
// 'ignore' method. This method does nothing, but can be called
|
||||
// to document the reason why the exception can be ignored.
|
||||
public static void ignore(Throwable e, String message) {
|
||||
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
void main() {
|
||||
// ...
|
||||
// BAD: Call to 'runFinalizersOnExit' forces execution of all finalizers on termination of
|
||||
// the runtime, which can cause live objects to transition to an invalid state.
|
||||
// Avoid using this method (and finalizers in general).
|
||||
System.runFinalizersOnExit(true);
|
||||
// ...
|
||||
void main() {
|
||||
// ...
|
||||
// BAD: Call to 'runFinalizersOnExit' forces execution of all finalizers on termination of
|
||||
// the runtime, which can cause live objects to transition to an invalid state.
|
||||
// Avoid using this method (and finalizers in general).
|
||||
System.runFinalizersOnExit(true);
|
||||
// ...
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
public static void main(String args[]) {
|
||||
String name = "John Doe";
|
||||
|
||||
// BAD: Unnecessary call to 'toString' on 'name'
|
||||
System.out.println("Hi, my name is " + name.toString());
|
||||
|
||||
// GOOD: No call to 'toString' on 'name'
|
||||
System.out.println("Hi, my name is " + name);
|
||||
public static void main(String args[]) {
|
||||
String name = "John Doe";
|
||||
|
||||
// BAD: Unnecessary call to 'toString' on 'name'
|
||||
System.out.println("Hi, my name is " + name.toString());
|
||||
|
||||
// GOOD: No call to 'toString' on 'name'
|
||||
System.out.println("Hi, my name is " + name);
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
// This class does not have a 'toString' method, so 'java.lang.Object.toString'
|
||||
// is used when the class is converted to a string.
|
||||
class WrongPerson {
|
||||
private String name;
|
||||
private Date birthDate;
|
||||
|
||||
public WrongPerson(String name, Date birthDate) {
|
||||
this.name =name;
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
WrongPerson wp = new WrongPerson("Robert Van Winkle", dateFormatter.parse("1967-10-31"));
|
||||
|
||||
// BAD: The following statement implicitly calls 'Object.toString',
|
||||
// which returns something similar to:
|
||||
// WrongPerson@4383f74d
|
||||
System.out.println(wp);
|
||||
// This class does not have a 'toString' method, so 'java.lang.Object.toString'
|
||||
// is used when the class is converted to a string.
|
||||
class WrongPerson {
|
||||
private String name;
|
||||
private Date birthDate;
|
||||
|
||||
public WrongPerson(String name, Date birthDate) {
|
||||
this.name =name;
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
WrongPerson wp = new WrongPerson("Robert Van Winkle", dateFormatter.parse("1967-10-31"));
|
||||
|
||||
// BAD: The following statement implicitly calls 'Object.toString',
|
||||
// which returns something similar to:
|
||||
// WrongPerson@4383f74d
|
||||
System.out.println(wp);
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
class RequestHandler extends Thread {
|
||||
private boolean isRunning;
|
||||
private Connection conn = new Connection();
|
||||
|
||||
public void run() {
|
||||
while (isRunning) {
|
||||
Request req = conn.getRequest();
|
||||
// Process the request ...
|
||||
|
||||
System.gc(); // This call may cause a garbage collection after each request.
|
||||
// This will likely reduce the throughput of the RequestHandler
|
||||
// because the JVM spends time on unnecessary garbage collection passes.
|
||||
}
|
||||
}
|
||||
class RequestHandler extends Thread {
|
||||
private boolean isRunning;
|
||||
private Connection conn = new Connection();
|
||||
|
||||
public void run() {
|
||||
while (isRunning) {
|
||||
Request req = conn.getRequest();
|
||||
// Process the request ...
|
||||
|
||||
System.gc(); // This call may cause a garbage collection after each request.
|
||||
// This will likely reduce the throughput of the RequestHandler
|
||||
// because the JVM spends time on unnecessary garbage collection passes.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,24 @@
|
||||
public static void main(String args[]) {
|
||||
String[] words = {"Who", "is", "John", "Galt"};
|
||||
String[][] wordMatrix = {{"There", "is"}, {"no", "spoon"}};
|
||||
|
||||
// BAD: This implicitly uses 'Object.toString' to convert the contents
|
||||
// of 'words[]', and prints out something similar to:
|
||||
// [Ljava.lang.String;@459189e1
|
||||
System.out.println(words);
|
||||
|
||||
// GOOD: 'Arrays.toString' calls 'toString' on
|
||||
// each of the array's elements. The statement prints out:
|
||||
// [Who, is, John, Galt]
|
||||
System.out.println(Arrays.toString(words));
|
||||
|
||||
// ALMOST RIGHT: This calls 'toString' on each of the multi-dimensional
|
||||
// array's elements. However, because the elements are arrays, the statement
|
||||
// prints out something similar to:
|
||||
// [[Ljava.lang.String;@55f33675, [Ljava.lang.String;@527c6768]]
|
||||
System.out.println(Arrays.toString(wordMatrix));
|
||||
|
||||
// GOOD: This properly prints out the contents of the multi-dimensional array:
|
||||
// [[There, is], [no, spoon]]
|
||||
System.out.println(Arrays.deepToString(wordMatrix));
|
||||
public static void main(String args[]) {
|
||||
String[] words = {"Who", "is", "John", "Galt"};
|
||||
String[][] wordMatrix = {{"There", "is"}, {"no", "spoon"}};
|
||||
|
||||
// BAD: This implicitly uses 'Object.toString' to convert the contents
|
||||
// of 'words[]', and prints out something similar to:
|
||||
// [Ljava.lang.String;@459189e1
|
||||
System.out.println(words);
|
||||
|
||||
// GOOD: 'Arrays.toString' calls 'toString' on
|
||||
// each of the array's elements. The statement prints out:
|
||||
// [Who, is, John, Galt]
|
||||
System.out.println(Arrays.toString(words));
|
||||
|
||||
// ALMOST RIGHT: This calls 'toString' on each of the multi-dimensional
|
||||
// array's elements. However, because the elements are arrays, the statement
|
||||
// prints out something similar to:
|
||||
// [[Ljava.lang.String;@55f33675, [Ljava.lang.String;@527c6768]]
|
||||
System.out.println(Arrays.toString(wordMatrix));
|
||||
|
||||
// GOOD: This properly prints out the contents of the multi-dimensional array:
|
||||
// [[There, is], [no, spoon]]
|
||||
System.out.println(Arrays.deepToString(wordMatrix));
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.java.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.java.dbscheme"/>
|
||||
<path value="/config/semmlecode.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.java.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.java.dbscheme"/>
|
||||
<path value="/config/semmlecode.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
||||
1
java/ql/test/library-tests/comments/.gitattributes
vendored
Normal file
1
java/ql/test/library-tests/comments/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestWindows.java eol=crlf
|
||||
@@ -1,22 +1,22 @@
|
||||
/**
|
||||
* A JavaDoc comment
|
||||
* with multiple lines.
|
||||
*/
|
||||
class TestWindows {
|
||||
/** A JavaDoc comment with a single line. */
|
||||
void m() {
|
||||
// a single-line comment
|
||||
// another single-line comment
|
||||
}
|
||||
|
||||
/* A block comment
|
||||
* with multiple lines.
|
||||
*/
|
||||
|
||||
/* A block comment with a single line. */
|
||||
|
||||
// an end-of-line comment with a spurious trailing comment marker */
|
||||
// an end-of-line comment with trailing whitespace
|
||||
//an end-of-line comment without a leading space
|
||||
void test() {} // an end-of-line comment with preceding code
|
||||
}
|
||||
/**
|
||||
* A JavaDoc comment
|
||||
* with multiple lines.
|
||||
*/
|
||||
class TestWindows {
|
||||
/** A JavaDoc comment with a single line. */
|
||||
void m() {
|
||||
// a single-line comment
|
||||
// another single-line comment
|
||||
}
|
||||
|
||||
/* A block comment
|
||||
* with multiple lines.
|
||||
*/
|
||||
|
||||
/* A block comment with a single line. */
|
||||
|
||||
// an end-of-line comment with a spurious trailing comment marker */
|
||||
// an end-of-line comment with trailing whitespace
|
||||
//an end-of-line comment without a leading space
|
||||
void test() {} // an end-of-line comment with preceding code
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
package successors;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class CloseReaderTest {
|
||||
public static String readPassword(File keyFile)
|
||||
{
|
||||
// TODO: use Console.readPassword() when it's available.
|
||||
System.out.print("Enter password for " + keyFile
|
||||
+ " (password will not be hidden): ");
|
||||
System.out.flush();
|
||||
BufferedReader stdin = new BufferedReader(new InputStreamReader(
|
||||
System.in));
|
||||
try
|
||||
{
|
||||
return stdin.readLine();
|
||||
} catch (IOException ex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
package successors;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class CloseReaderTest {
|
||||
public static String readPassword(File keyFile)
|
||||
{
|
||||
// TODO: use Console.readPassword() when it's available.
|
||||
System.out.print("Enter password for " + keyFile
|
||||
+ " (password will not be hidden): ");
|
||||
System.out.flush();
|
||||
BufferedReader stdin = new BufferedReader(new InputStreamReader(
|
||||
System.in));
|
||||
try
|
||||
{
|
||||
return stdin.readLine();
|
||||
} catch (IOException ex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package successors;
|
||||
|
||||
public class LoopVarReadTest {
|
||||
public static void testLoop()
|
||||
{
|
||||
int x = 2;
|
||||
for (int y = 0; y < 10; y += x)
|
||||
{
|
||||
System.out.println("Foo");
|
||||
}
|
||||
|
||||
int q = 10;
|
||||
|
||||
System.out.println("foo");
|
||||
}
|
||||
}
|
||||
package successors;
|
||||
|
||||
public class LoopVarReadTest {
|
||||
public static void testLoop()
|
||||
{
|
||||
int x = 2;
|
||||
for (int y = 0; y < 10; y += x)
|
||||
{
|
||||
System.out.println("Foo");
|
||||
}
|
||||
|
||||
int q = 10;
|
||||
|
||||
System.out.println("foo");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
package successors;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
|
||||
public class SaveFileTest {
|
||||
public void saveFile(String path, String contentType,
|
||||
long size, InputStream is) throws FileNotFoundException,
|
||||
IOException
|
||||
{
|
||||
|
||||
String savePath = path;
|
||||
if (path.startsWith("/"))
|
||||
{
|
||||
savePath = path.substring(1);
|
||||
}
|
||||
|
||||
// make sure uploads area exists for this weblog
|
||||
File dirPath = new File("foo");
|
||||
File saveFile = new File(dirPath.getAbsolutePath() + File.separator
|
||||
+ savePath);
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead = 0;
|
||||
OutputStream bos = null;
|
||||
try
|
||||
{
|
||||
bos = new FileOutputStream(saveFile);
|
||||
while ((bytesRead = is.read(buffer, 0, 8192)) != -1)
|
||||
{
|
||||
bos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
|
||||
System.out.println("The file has been written to ["
|
||||
+ saveFile.getAbsolutePath() + "]");
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new IOException("ERROR uploading file", e);
|
||||
} finally
|
||||
{
|
||||
try
|
||||
{
|
||||
bos.flush();
|
||||
bos.close();
|
||||
} catch (Exception ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package successors;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
|
||||
public class SaveFileTest {
|
||||
public void saveFile(String path, String contentType,
|
||||
long size, InputStream is) throws FileNotFoundException,
|
||||
IOException
|
||||
{
|
||||
|
||||
String savePath = path;
|
||||
if (path.startsWith("/"))
|
||||
{
|
||||
savePath = path.substring(1);
|
||||
}
|
||||
|
||||
// make sure uploads area exists for this weblog
|
||||
File dirPath = new File("foo");
|
||||
File saveFile = new File(dirPath.getAbsolutePath() + File.separator
|
||||
+ savePath);
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead = 0;
|
||||
OutputStream bos = null;
|
||||
try
|
||||
{
|
||||
bos = new FileOutputStream(saveFile);
|
||||
while ((bytesRead = is.read(buffer, 0, 8192)) != -1)
|
||||
{
|
||||
bos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
|
||||
System.out.println("The file has been written to ["
|
||||
+ saveFile.getAbsolutePath() + "]");
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new IOException("ERROR uploading file", e);
|
||||
} finally
|
||||
{
|
||||
try
|
||||
{
|
||||
bos.flush();
|
||||
bos.close();
|
||||
} catch (Exception ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +1,86 @@
|
||||
package successors;
|
||||
|
||||
public class TestBreak {
|
||||
public void f()
|
||||
{
|
||||
//loop breaks
|
||||
a:
|
||||
for (;;)
|
||||
{
|
||||
int x = 1;
|
||||
x = x + 1;
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
for (int q : new int[20])
|
||||
{
|
||||
if (q == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
break a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int y = 12;
|
||||
while (true)
|
||||
{
|
||||
if (y == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (y == 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
y = y + 2;
|
||||
} while (y == 1);
|
||||
y = 12;
|
||||
}
|
||||
}
|
||||
y = 13;
|
||||
|
||||
//switch breaks
|
||||
int x =12;
|
||||
switch (x)
|
||||
{
|
||||
case 1:
|
||||
x = x + 1;
|
||||
y = y + 1;
|
||||
case 2:
|
||||
x = x + 2;
|
||||
y = y + 2;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
x = x + 3;
|
||||
y = y + 4;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
x = x + 5;
|
||||
y = y + 6;
|
||||
default:
|
||||
x = y;
|
||||
y = x;
|
||||
}
|
||||
|
||||
//no default
|
||||
switch(x)
|
||||
{
|
||||
case 1:
|
||||
x = 1;
|
||||
break;
|
||||
case 2:
|
||||
x = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
package successors;
|
||||
|
||||
public class TestBreak {
|
||||
public void f()
|
||||
{
|
||||
//loop breaks
|
||||
a:
|
||||
for (;;)
|
||||
{
|
||||
int x = 1;
|
||||
x = x + 1;
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
for (int q : new int[20])
|
||||
{
|
||||
if (q == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
break a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int y = 12;
|
||||
while (true)
|
||||
{
|
||||
if (y == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (y == 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
y = y + 2;
|
||||
} while (y == 1);
|
||||
y = 12;
|
||||
}
|
||||
}
|
||||
y = 13;
|
||||
|
||||
//switch breaks
|
||||
int x =12;
|
||||
switch (x)
|
||||
{
|
||||
case 1:
|
||||
x = x + 1;
|
||||
y = y + 1;
|
||||
case 2:
|
||||
x = x + 2;
|
||||
y = y + 2;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
x = x + 3;
|
||||
y = y + 4;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
x = x + 5;
|
||||
y = y + 6;
|
||||
default:
|
||||
x = y;
|
||||
y = x;
|
||||
}
|
||||
|
||||
//no default
|
||||
switch(x)
|
||||
{
|
||||
case 1:
|
||||
x = 1;
|
||||
break;
|
||||
case 2:
|
||||
x = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
package successors;
|
||||
|
||||
public class TestContinue {
|
||||
public void f()
|
||||
{
|
||||
//loop breaks
|
||||
a:
|
||||
for (int p = 0; p < 10;)
|
||||
{
|
||||
int x = 1;
|
||||
x = x + 1;
|
||||
if (x == 1)
|
||||
{
|
||||
continue;
|
||||
} else
|
||||
{
|
||||
for (int q : new int[20])
|
||||
{
|
||||
if (q == 1)
|
||||
{
|
||||
continue;
|
||||
} else if (q == 2)
|
||||
{
|
||||
continue a;
|
||||
}
|
||||
q = 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
int y = 12;
|
||||
while (y != 13)
|
||||
{
|
||||
if (y == 1)
|
||||
{
|
||||
continue;
|
||||
} else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (y == 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
y = y + 2;
|
||||
} while (y == 1);
|
||||
y = 12;
|
||||
}
|
||||
y = 15;
|
||||
}
|
||||
y = 13;
|
||||
while (y != 12)
|
||||
{
|
||||
if (y != 6)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
package successors;
|
||||
|
||||
public class TestContinue {
|
||||
public void f()
|
||||
{
|
||||
//loop breaks
|
||||
a:
|
||||
for (int p = 0; p < 10;)
|
||||
{
|
||||
int x = 1;
|
||||
x = x + 1;
|
||||
if (x == 1)
|
||||
{
|
||||
continue;
|
||||
} else
|
||||
{
|
||||
for (int q : new int[20])
|
||||
{
|
||||
if (q == 1)
|
||||
{
|
||||
continue;
|
||||
} else if (q == 2)
|
||||
{
|
||||
continue a;
|
||||
}
|
||||
q = 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
int y = 12;
|
||||
while (y != 13)
|
||||
{
|
||||
if (y == 1)
|
||||
{
|
||||
continue;
|
||||
} else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (y == 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
y = y + 2;
|
||||
} while (y == 1);
|
||||
y = 12;
|
||||
}
|
||||
y = 15;
|
||||
}
|
||||
y = 13;
|
||||
while (y != 12)
|
||||
{
|
||||
if (y != 6)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
package successors;
|
||||
|
||||
public class TestFinally {
|
||||
public void f()
|
||||
{
|
||||
int z = 12;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex2)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
System.out.println("Foo");
|
||||
int y = 12 + 3;
|
||||
System.out.println("Bar");
|
||||
y = y + 1;
|
||||
return;
|
||||
} catch (Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
int x = 1;
|
||||
System.out.println("Error: " + e);
|
||||
x = x + 1;
|
||||
} finally
|
||||
{
|
||||
int y = 12;
|
||||
System.out.println("Finally");
|
||||
y = y + 1;
|
||||
}
|
||||
z = z + 1;
|
||||
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
|
||||
z = z + 2;
|
||||
}
|
||||
}
|
||||
package successors;
|
||||
|
||||
public class TestFinally {
|
||||
public void f()
|
||||
{
|
||||
int z = 12;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex2)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
System.out.println("Foo");
|
||||
int y = 12 + 3;
|
||||
System.out.println("Bar");
|
||||
y = y + 1;
|
||||
return;
|
||||
} catch (Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
int x = 1;
|
||||
System.out.println("Error: " + e);
|
||||
x = x + 1;
|
||||
} finally
|
||||
{
|
||||
int y = 12;
|
||||
System.out.println("Finally");
|
||||
y = y + 1;
|
||||
}
|
||||
z = z + 1;
|
||||
|
||||
try
|
||||
{
|
||||
System.out.println("Try1");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Try2");
|
||||
} catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("Finally");
|
||||
if (z == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
System.out.println("Finally2");
|
||||
}
|
||||
|
||||
z = z + 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,108 +1,108 @@
|
||||
package successors;
|
||||
|
||||
public class TestFinallyBreakContinue {
|
||||
public void f()
|
||||
{
|
||||
int x = 1;
|
||||
a:
|
||||
for (;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
}
|
||||
|
||||
b:
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i : new int[20])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break b;
|
||||
} else
|
||||
{
|
||||
continue b;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
}
|
||||
package successors;
|
||||
|
||||
public class TestFinallyBreakContinue {
|
||||
public void f()
|
||||
{
|
||||
int x = 1;
|
||||
a:
|
||||
for (;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
}
|
||||
|
||||
b:
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i : new int[20])
|
||||
{
|
||||
try
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break;
|
||||
} else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
if (x == 1)
|
||||
{
|
||||
break b;
|
||||
} else
|
||||
{
|
||||
continue b;
|
||||
}
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
System.out.println("Exception");
|
||||
} finally
|
||||
{
|
||||
System.out.println("finally");
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,120 +1,120 @@
|
||||
package successors;
|
||||
|
||||
public class TestLoopBranch {
|
||||
int xx = 12;
|
||||
int yy = 13;
|
||||
|
||||
public void f()
|
||||
{
|
||||
int x = 1;
|
||||
int y = 2;
|
||||
System.out.println("foo");
|
||||
|
||||
do
|
||||
{
|
||||
System.out.println("bar");
|
||||
System.out.println("foobar");
|
||||
} while (x == 2);
|
||||
|
||||
{
|
||||
System.out.println("shazam");
|
||||
System.out.println("boogie");
|
||||
}
|
||||
|
||||
while (x == 1)
|
||||
{
|
||||
System.out.println("wonderland");
|
||||
System.out.println("shodan");
|
||||
x = x + 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
System.out.println("rapture");
|
||||
y = x - 2;
|
||||
}
|
||||
|
||||
;
|
||||
;
|
||||
|
||||
for (int j : new int[20])
|
||||
{
|
||||
System.out.println("Zero : " + j);
|
||||
j = j + x;
|
||||
}
|
||||
|
||||
if (y == -1)
|
||||
{
|
||||
System.out.println("i squared");
|
||||
}
|
||||
|
||||
if (x == 42)
|
||||
{
|
||||
System.out.println("rat");
|
||||
x = 6 * 9;
|
||||
} else
|
||||
{
|
||||
System.out.println("arr");
|
||||
x = y * x;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (x)
|
||||
{
|
||||
case 1:
|
||||
x = x + 1;
|
||||
y = y + 1;
|
||||
case 2:
|
||||
x = x + 2;
|
||||
y = y + 2;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
x = x + 3;
|
||||
y = y + 4;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
x = x + 5;
|
||||
y = y + 6;
|
||||
default:
|
||||
x = y;
|
||||
y = x;
|
||||
}
|
||||
|
||||
//no default
|
||||
switch(x)
|
||||
{
|
||||
case 1:
|
||||
x = 1;
|
||||
break;
|
||||
case 2:
|
||||
x = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
Comparable<String> b = new Comparable<String>() {
|
||||
@Override
|
||||
public int compareTo(String o)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
b.compareTo("Foo");
|
||||
|
||||
x = x + y;
|
||||
return;
|
||||
}
|
||||
|
||||
public TestLoopBranch()
|
||||
{
|
||||
xx = 33;
|
||||
yy = 44;
|
||||
}
|
||||
|
||||
public TestLoopBranch(int i)
|
||||
{
|
||||
xx = i;
|
||||
yy = i;
|
||||
}
|
||||
package successors;
|
||||
|
||||
public class TestLoopBranch {
|
||||
int xx = 12;
|
||||
int yy = 13;
|
||||
|
||||
public void f()
|
||||
{
|
||||
int x = 1;
|
||||
int y = 2;
|
||||
System.out.println("foo");
|
||||
|
||||
do
|
||||
{
|
||||
System.out.println("bar");
|
||||
System.out.println("foobar");
|
||||
} while (x == 2);
|
||||
|
||||
{
|
||||
System.out.println("shazam");
|
||||
System.out.println("boogie");
|
||||
}
|
||||
|
||||
while (x == 1)
|
||||
{
|
||||
System.out.println("wonderland");
|
||||
System.out.println("shodan");
|
||||
x = x + 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
System.out.println("rapture");
|
||||
y = x - 2;
|
||||
}
|
||||
|
||||
;
|
||||
;
|
||||
|
||||
for (int j : new int[20])
|
||||
{
|
||||
System.out.println("Zero : " + j);
|
||||
j = j + x;
|
||||
}
|
||||
|
||||
if (y == -1)
|
||||
{
|
||||
System.out.println("i squared");
|
||||
}
|
||||
|
||||
if (x == 42)
|
||||
{
|
||||
System.out.println("rat");
|
||||
x = 6 * 9;
|
||||
} else
|
||||
{
|
||||
System.out.println("arr");
|
||||
x = y * x;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (x)
|
||||
{
|
||||
case 1:
|
||||
x = x + 1;
|
||||
y = y + 1;
|
||||
case 2:
|
||||
x = x + 2;
|
||||
y = y + 2;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
x = x + 3;
|
||||
y = y + 4;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
x = x + 5;
|
||||
y = y + 6;
|
||||
default:
|
||||
x = y;
|
||||
y = x;
|
||||
}
|
||||
|
||||
//no default
|
||||
switch(x)
|
||||
{
|
||||
case 1:
|
||||
x = 1;
|
||||
break;
|
||||
case 2:
|
||||
x = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
Comparable<String> b = new Comparable<String>() {
|
||||
@Override
|
||||
public int compareTo(String o)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
b.compareTo("Foo");
|
||||
|
||||
x = x + y;
|
||||
return;
|
||||
}
|
||||
|
||||
public TestLoopBranch()
|
||||
{
|
||||
xx = 33;
|
||||
yy = 44;
|
||||
}
|
||||
|
||||
public TestLoopBranch(int i)
|
||||
{
|
||||
xx = i;
|
||||
yy = i;
|
||||
}
|
||||
}
|
||||
@@ -1,135 +1,135 @@
|
||||
package successors;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidParameterException;
|
||||
|
||||
public class TestThrow {
|
||||
private TestThrow() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
private void thrower() throws InvalidParameterException
|
||||
{
|
||||
}
|
||||
|
||||
public void f() throws Exception
|
||||
{
|
||||
int z = 0;
|
||||
try
|
||||
{
|
||||
throw new RuntimeException();
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
z = 1;
|
||||
} catch (Exception e)
|
||||
{
|
||||
z = 2;
|
||||
}
|
||||
|
||||
z = -1;
|
||||
|
||||
try
|
||||
{
|
||||
if (z == 1)
|
||||
{
|
||||
throw new RuntimeException();
|
||||
} else if (z == 2)
|
||||
{
|
||||
throw new Exception();
|
||||
} else if (z == 3)
|
||||
{
|
||||
new TestThrow();
|
||||
} else
|
||||
{
|
||||
thrower();
|
||||
}
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
z = 1;
|
||||
} finally
|
||||
{
|
||||
z = 2;
|
||||
}
|
||||
|
||||
z = -1;
|
||||
|
||||
try
|
||||
{
|
||||
if (z == 1)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
else if (z == 2)
|
||||
{
|
||||
new TestThrow();
|
||||
} else
|
||||
{
|
||||
thrower();
|
||||
}
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
z = 1;
|
||||
}
|
||||
|
||||
z = -1;
|
||||
|
||||
try
|
||||
{
|
||||
if (z == 1)
|
||||
throw new Exception();
|
||||
} finally
|
||||
{
|
||||
z = 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (z == 1)
|
||||
{
|
||||
throw new Exception();
|
||||
} else if (z == 2)
|
||||
{
|
||||
throw new RuntimeException();
|
||||
} else
|
||||
{
|
||||
throw new IOException("Foo bar", null);
|
||||
}
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
z = 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
z = -2;
|
||||
} finally
|
||||
{
|
||||
if (z == 1)
|
||||
{
|
||||
throw new Exception();
|
||||
} else if (z == 2)
|
||||
{
|
||||
throw new RuntimeException();
|
||||
} else if (z == 3)
|
||||
{
|
||||
throw new IOException("Foo bar", null);
|
||||
}
|
||||
}
|
||||
} catch (IOException e)
|
||||
{
|
||||
z = 2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
z = 3;
|
||||
}
|
||||
|
||||
if (z == 1)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
z = -1;
|
||||
}
|
||||
}
|
||||
package successors;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidParameterException;
|
||||
|
||||
public class TestThrow {
|
||||
private TestThrow() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
private void thrower() throws InvalidParameterException
|
||||
{
|
||||
}
|
||||
|
||||
public void f() throws Exception
|
||||
{
|
||||
int z = 0;
|
||||
try
|
||||
{
|
||||
throw new RuntimeException();
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
z = 1;
|
||||
} catch (Exception e)
|
||||
{
|
||||
z = 2;
|
||||
}
|
||||
|
||||
z = -1;
|
||||
|
||||
try
|
||||
{
|
||||
if (z == 1)
|
||||
{
|
||||
throw new RuntimeException();
|
||||
} else if (z == 2)
|
||||
{
|
||||
throw new Exception();
|
||||
} else if (z == 3)
|
||||
{
|
||||
new TestThrow();
|
||||
} else
|
||||
{
|
||||
thrower();
|
||||
}
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
z = 1;
|
||||
} finally
|
||||
{
|
||||
z = 2;
|
||||
}
|
||||
|
||||
z = -1;
|
||||
|
||||
try
|
||||
{
|
||||
if (z == 1)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
else if (z == 2)
|
||||
{
|
||||
new TestThrow();
|
||||
} else
|
||||
{
|
||||
thrower();
|
||||
}
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
z = 1;
|
||||
}
|
||||
|
||||
z = -1;
|
||||
|
||||
try
|
||||
{
|
||||
if (z == 1)
|
||||
throw new Exception();
|
||||
} finally
|
||||
{
|
||||
z = 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (z == 1)
|
||||
{
|
||||
throw new Exception();
|
||||
} else if (z == 2)
|
||||
{
|
||||
throw new RuntimeException();
|
||||
} else
|
||||
{
|
||||
throw new IOException("Foo bar", null);
|
||||
}
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
z = 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
z = -2;
|
||||
} finally
|
||||
{
|
||||
if (z == 1)
|
||||
{
|
||||
throw new Exception();
|
||||
} else if (z == 2)
|
||||
{
|
||||
throw new RuntimeException();
|
||||
} else if (z == 3)
|
||||
{
|
||||
throw new IOException("Foo bar", null);
|
||||
}
|
||||
}
|
||||
} catch (IOException e)
|
||||
{
|
||||
z = 2;
|
||||
}
|
||||
finally
|
||||
{
|
||||
z = 3;
|
||||
}
|
||||
|
||||
if (z == 1)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
z = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
package successors;
|
||||
|
||||
public class TestTryCatch {
|
||||
public void f()
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Foo");
|
||||
int y = 12 + 3;
|
||||
System.out.println("Bar");
|
||||
y = y + 1;
|
||||
} catch (Exception e)
|
||||
{
|
||||
int x = 1;
|
||||
System.out.println("Error: " + e);
|
||||
x = x + 1;
|
||||
return;
|
||||
} finally
|
||||
{
|
||||
int y = 12;
|
||||
System.out.println("Finally");
|
||||
y = y + 1;
|
||||
}
|
||||
int z = 12;
|
||||
z = z + 1;
|
||||
|
||||
for (int q = 0; q < 10; q++)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Foo");
|
||||
int y = 12 + 3;
|
||||
System.out.println("Bar");
|
||||
y = y + 1;
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
int x = 1;
|
||||
System.out.println("Error: " + e);
|
||||
x = x + 1;
|
||||
}
|
||||
}
|
||||
z = z + 2;
|
||||
}
|
||||
}
|
||||
package successors;
|
||||
|
||||
public class TestTryCatch {
|
||||
public void f()
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Foo");
|
||||
int y = 12 + 3;
|
||||
System.out.println("Bar");
|
||||
y = y + 1;
|
||||
} catch (Exception e)
|
||||
{
|
||||
int x = 1;
|
||||
System.out.println("Error: " + e);
|
||||
x = x + 1;
|
||||
return;
|
||||
} finally
|
||||
{
|
||||
int y = 12;
|
||||
System.out.println("Finally");
|
||||
y = y + 1;
|
||||
}
|
||||
int z = 12;
|
||||
z = z + 1;
|
||||
|
||||
for (int q = 0; q < 10; q++)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Foo");
|
||||
int y = 12 + 3;
|
||||
System.out.println("Bar");
|
||||
y = y + 1;
|
||||
} catch (RuntimeException e)
|
||||
{
|
||||
int x = 1;
|
||||
System.out.println("Error: " + e);
|
||||
x = x + 1;
|
||||
}
|
||||
}
|
||||
z = z + 2;
|
||||
}
|
||||
}
|
||||
|
||||
1
java/ql/test/query-tests/AlertSuppression/.gitattributes
vendored
Normal file
1
java/ql/test/query-tests/AlertSuppression/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestWindows.java eol=crlf
|
||||
@@ -1,28 +1,28 @@
|
||||
class TestWindows {} // lgtm
|
||||
// lgtm[java/confusing-method-name]
|
||||
// lgtm[java/confusing-method-name, java/non-short-circuit-evaluation]
|
||||
// lgtm[@tag:exceptions]
|
||||
// lgtm[@tag:exceptions,java/confusing-method-name]
|
||||
// lgtm[@expires:2017-06-11]
|
||||
// lgtm[java/confusing-method-name] does not seem confusing despite alert by lgtm
|
||||
// lgtm: blah blah
|
||||
// lgtm blah blah #falsepositive
|
||||
//lgtm [java/confusing-method-name]
|
||||
/* lgtm */
|
||||
// lgtm[]
|
||||
// lgtmfoo
|
||||
//lgtm
|
||||
// lgtm
|
||||
// lgtm [java/confusing-method-name]
|
||||
// foolgtm[java/confusing-method-name]
|
||||
// foolgtm
|
||||
// foo; lgtm
|
||||
// foo; lgtm[java/confusing-method-name]
|
||||
// foo lgtm
|
||||
// foo lgtm[java/confusing-method-name]
|
||||
// foo lgtm bar
|
||||
// foo lgtm[java/confusing-method-name] bar
|
||||
// LGTM!
|
||||
// LGTM[java/confusing-method-name]
|
||||
//lgtm[java/confusing-method-name] and lgtm[java/non-short-circuit-evaluation]
|
||||
//lgtm[java/confusing-method-name]; lgtm
|
||||
class TestWindows {} // lgtm
|
||||
// lgtm[java/confusing-method-name]
|
||||
// lgtm[java/confusing-method-name, java/non-short-circuit-evaluation]
|
||||
// lgtm[@tag:exceptions]
|
||||
// lgtm[@tag:exceptions,java/confusing-method-name]
|
||||
// lgtm[@expires:2017-06-11]
|
||||
// lgtm[java/confusing-method-name] does not seem confusing despite alert by lgtm
|
||||
// lgtm: blah blah
|
||||
// lgtm blah blah #falsepositive
|
||||
//lgtm [java/confusing-method-name]
|
||||
/* lgtm */
|
||||
// lgtm[]
|
||||
// lgtmfoo
|
||||
//lgtm
|
||||
// lgtm
|
||||
// lgtm [java/confusing-method-name]
|
||||
// foolgtm[java/confusing-method-name]
|
||||
// foolgtm
|
||||
// foo; lgtm
|
||||
// foo; lgtm[java/confusing-method-name]
|
||||
// foo lgtm
|
||||
// foo lgtm[java/confusing-method-name]
|
||||
// foo lgtm bar
|
||||
// foo lgtm[java/confusing-method-name] bar
|
||||
// LGTM!
|
||||
// LGTM[java/confusing-method-name]
|
||||
//lgtm[java/confusing-method-name] and lgtm[java/non-short-circuit-evaluation]
|
||||
//lgtm[java/confusing-method-name]; lgtm
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-javascript-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.javascript.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.javascript.dbscheme"/>
|
||||
<path value="/semmlecode.javascript.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.2"?>
|
||||
<plugin>
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="semmlecode-javascript-queries"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.javascript.library"/>
|
||||
</extension>
|
||||
|
||||
<extension point="com.semmle.plugin.qdt.ui.resources">
|
||||
<name value="com.semmle.code.javascript.dbscheme"/>
|
||||
<path value="/semmlecode.javascript.dbscheme"/>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
||||
Reference in New Issue
Block a user