RULEAPI-661: Add syntax coloring

This commit is contained in:
Fred Tingaud 2022-02-04 17:28:24 +01:00 committed by GitHub
parent 04655f1ee7
commit b4161466e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4472 changed files with 11180 additions and 985 deletions

View File

@ -26,7 +26,7 @@ cd rspec-tools
if pipenv run rspec-tools check-description --d ../out; then
echo "rule.adoc is fine"
else
echo "ERROR: rule.adoc is not valid"
echo "ERROR: There are invalid rule.adoc"
exit_code=1
fi
cd ..

View File

@ -12,6 +12,31 @@ include::section_names.adoc[]
Third level titles are not checked.
== Code Examples
Whenever possible, prefix your code blocks with `[source,language]`, in order to get syntax coloring.
....
[source,cpp]
----
int main(int argc, const char** argv) {
return 0;
}
----
....
That is mandatory for the Noncompliant and Compliant code example sections, just recommended - at the moment - for other sections.
The language names accepted are usually the name we already use for the language folders in RSPEC. Exceptions are:
cfamily:: use `cpp`, `c`, or `objectivec`
plsql:: use `sql`
tsql:: use `sql`
In case no language is appropriate for a code block (for example shared examples between multiple languages), you can use `text` as the language.
== Parameters
Parameters should be listed in a subsection as follow:

View File

@ -20,6 +20,7 @@
"@types/react": "^16.14.2",
"@types/react-dom": "^16.9.10",
"asciidoctor": "^2.2.1",
"html-react-parser": "^1.4.6",
"lunr": "^2.3.9",
"nodegit": "^0.27.0",
"react": "^17.0.1",
@ -9718,6 +9719,44 @@
"safe-buffer": "~5.1.0"
}
},
"node_modules/html-dom-parser": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-1.0.4.tgz",
"integrity": "sha512-ThM/vK/18R5/cVB9UsqhNqbJU7LE2BmSA7C/FjYV88wIDW75GSUpvSE/JxE4mJ8bOuU6Kp15/I1giM2JbD+ieA==",
"dependencies": {
"domhandler": "4.3.0",
"htmlparser2": "7.2.0"
}
},
"node_modules/html-dom-parser/node_modules/entities": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
"integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/html-dom-parser/node_modules/htmlparser2": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz",
"integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.2",
"domutils": "^2.8.0",
"entities": "^3.0.1"
}
},
"node_modules/html-encoding-sniffer": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@ -9759,6 +9798,20 @@
"node": ">=12"
}
},
"node_modules/html-react-parser": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-1.4.6.tgz",
"integrity": "sha512-tbKIw/aPsOmTZUs7sTSDDzfnBSAfHu8RpoNY8QhHloB//lr9eEM7qkzNbf/eXo4XIdo8ykZpB7ECQp3k+Iz10A==",
"dependencies": {
"domhandler": "4.3.0",
"html-dom-parser": "1.0.4",
"react-property": "2.0.0",
"style-to-js": "1.1.0"
},
"peerDependencies": {
"react": "0.14 || 15 || 16 || 17"
}
},
"node_modules/html-webpack-plugin": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz",
@ -10056,6 +10109,11 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"node_modules/inline-style-parser": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
},
"node_modules/internal-slot": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
@ -16690,6 +16748,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-property": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz",
"integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw=="
},
"node_modules/react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@ -18093,6 +18156,22 @@
"webpack": "^5.0.0"
}
},
"node_modules/style-to-js": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.0.tgz",
"integrity": "sha512-1OqefPDxGrlMwcbfpsTVRyzwdhr4W0uxYQzeA2F1CBc8WG04udg2+ybRnvh3XYL4TdHQrCahLtax2jc8xaE6rA==",
"dependencies": {
"style-to-object": "0.3.0"
}
},
"node_modules/style-to-object": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz",
"integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==",
"dependencies": {
"inline-style-parser": "0.1.1"
}
},
"node_modules/stylehacks": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.1.tgz",
@ -27318,6 +27397,33 @@
}
}
},
"html-dom-parser": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-1.0.4.tgz",
"integrity": "sha512-ThM/vK/18R5/cVB9UsqhNqbJU7LE2BmSA7C/FjYV88wIDW75GSUpvSE/JxE4mJ8bOuU6Kp15/I1giM2JbD+ieA==",
"requires": {
"domhandler": "4.3.0",
"htmlparser2": "7.2.0"
},
"dependencies": {
"entities": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
"integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q=="
},
"htmlparser2": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz",
"integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.2",
"domutils": "^2.8.0",
"entities": "^3.0.1"
}
}
}
},
"html-encoding-sniffer": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@ -27350,6 +27456,17 @@
"terser": "^5.10.0"
}
},
"html-react-parser": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-1.4.6.tgz",
"integrity": "sha512-tbKIw/aPsOmTZUs7sTSDDzfnBSAfHu8RpoNY8QhHloB//lr9eEM7qkzNbf/eXo4XIdo8ykZpB7ECQp3k+Iz10A==",
"requires": {
"domhandler": "4.3.0",
"html-dom-parser": "1.0.4",
"react-property": "2.0.0",
"style-to-js": "1.1.0"
}
},
"html-webpack-plugin": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz",
@ -27568,6 +27685,11 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"inline-style-parser": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
},
"internal-slot": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
@ -32374,6 +32496,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-property": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz",
"integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw=="
},
"react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@ -33451,6 +33578,22 @@
"integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==",
"requires": {}
},
"style-to-js": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.0.tgz",
"integrity": "sha512-1OqefPDxGrlMwcbfpsTVRyzwdhr4W0uxYQzeA2F1CBc8WG04udg2+ybRnvh3XYL4TdHQrCahLtax2jc8xaE6rA==",
"requires": {
"style-to-object": "0.3.0"
}
},
"style-to-object": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz",
"integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==",
"requires": {
"inline-style-parser": "0.1.1"
}
},
"stylehacks": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.1.tgz",

View File

@ -16,6 +16,7 @@
"@types/react": "^16.14.2",
"@types/react-dom": "^16.9.10",
"asciidoctor": "^2.2.1",
"html-react-parser": "^1.4.6",
"lunr": "^2.3.9",
"nodegit": "^0.27.0",
"react": "^17.0.1",

View File

@ -12,6 +12,7 @@ import { Link as RouterLink, useHistory } from 'react-router-dom';
import { RULE_STATE, useRuleCoverage } from './utils/useRuleCoverage';
import { useFetch } from './utils/useFetch';
import { RuleMetadata } from './types';
import parse, {domToReact, Element} from 'html-react-parser';
import './hljs-humanoid-light.css';
@ -324,7 +325,15 @@ function useDescription(metadata: PageMetadata, ruleid: string, language: string
if (descHTML !== null && !descIsLoading && !descError) {
return <div>
<div dangerouslySetInnerHTML={{ __html: descHTML }} />
{parse(descHTML, {
replace: (d) => {
const domNode = d as Element;
if (domNode.name === 'code' && domNode.attribs && domNode.attribs['data-lang']) {
return <Highlight className={domNode.attribs['data-lang']}>{domToReact(domNode.children)}</Highlight>;
}
}
})
}
<hr />
<a href={editOnGithubUrl}>Edit on Github</a><br />
<hr />

View File

@ -9,7 +9,7 @@ import { fetchMock } from '../testutils'
const rulesPath = path.join(__dirname, '..', 'deployment', '__tests__', 'resources', 'metadata');
function readRuleFile(ruleId, filename) {
function readRuleFile(ruleId: string, filename: string) {
return fs.readFileSync(path.join(rulesPath, ruleId, filename)).toString();
}
@ -21,7 +21,7 @@ beforeEach(() => {
const specS3457 = readRuleFile('S3457', 'csharp-description.html');
const metadataS3457 = readRuleFile('S3457', 'csharp-metadata.json');
const rootUrl = process.env.PUBLIC_URL;
let mockUrls = {};
let mockUrls: {[index: string]:any} = {};
mockUrls[`${rootUrl}/rules/S1000/cfamily-description.html`] = {text: specS1000};
mockUrls[`${rootUrl}/rules/S1000/cfamily-metadata.json`] = {json: JSON.parse(metadataS1000)};
mockUrls[`${rootUrl}/rules/S1007/default-description.html`] = {text: specS1007};
@ -35,7 +35,7 @@ beforeEach(() => {
'CSH' : {'S3457': 'c#1'},
'C': {'S100': 'c1', 'S234': {'since': 'c2', 'until': 'c3'}}}
};
jest.spyOn(global, 'fetch').mockImplementation(fetchMock(mockUrls));
jest.spyOn(global, 'fetch').mockImplementation(fetchMock(mockUrls) as jest.Mocked<typeof fetch>);
});
afterEach(() => {

View File

@ -13,9 +13,9 @@ jest.setTimeout(20000);
function genMockUrls() {
const rulePath = path.join(__dirname, '..', 'deployment', '__tests__', 'resources', 'metadata');
const [indexStore, indexAggregates] = buildIndexStore(rulePath);
const searchIndex = buildSearchIndex(indexStore);
const searchIndex: lunr.Index = buildSearchIndex(indexStore);
const rootUrl = process.env.PUBLIC_URL;
let mockUrls = {};
let mockUrls: {[index: string]: any} = {};
mockUrls[`${rootUrl}/rules/rule-index.json`] = {json: normalize(searchIndex)};
mockUrls[`${rootUrl}/rules/rule-index-store.json`] = {json: normalize(indexStore)};
mockUrls[`${rootUrl}/rules/rule-index-aggregates.json`] = {json: normalize(indexAggregates)};
@ -30,7 +30,7 @@ function genMockUrls() {
let fetchMocker = fetchMockObject(genMockUrls());
beforeEach(() => {
jest.spyOn(global, 'fetch').mockImplementation(fetchMocker.mock);
jest.spyOn(global, 'fetch').mockImplementation(fetchMocker.mock as jest.Mocked<typeof fetch>);
});
afterEach(() => {
@ -50,7 +50,7 @@ async function renderDefaultSearchPageWithHistory() {
}
async function renderDefaultSearchPage() {
const {renderResult, _} = await renderDefaultSearchPageWithHistory();
const { renderResult } = await renderDefaultSearchPageWithHistory();
expect(renderResult.queryByTestId('search-hit-S1000')).not.toBeNull();
expect(renderResult.queryByText(/rules found: 4/i)).not.toBeNull();
@ -78,7 +78,7 @@ test('narrows search by title', async () => {
});
test('on enter navigates to the ruleid', async () => {
const { renderResult: {queryByText, getByRole}, history } = await renderDefaultSearchPageWithHistory();
const { renderResult: { getByRole }, history } = await renderDefaultSearchPageWithHistory();
// Enter a search query
const searchBox = getByRole('textbox');
@ -90,7 +90,7 @@ test('on enter navigates to the ruleid', async () => {
});
test('on enter does not navigate to the wrong ruleid', async () => {
const { renderResult: {queryByText, getByRole}, history } = await renderDefaultSearchPageWithHistory();
const { renderResult: { getByRole }, history } = await renderDefaultSearchPageWithHistory();
// Enter a search query
const searchBox = getByRole('textbox');
@ -102,7 +102,7 @@ test('on enter does not navigate to the wrong ruleid', async () => {
});
test('does nothing on keyup other than enter', async () => {
const { renderResult: {queryByText, getByRole}, history } = await renderDefaultSearchPageWithHistory();
const { renderResult: { getByRole }, history } = await renderDefaultSearchPageWithHistory();
// Enter a search query
const searchBox = getByRole('textbox');

File diff suppressed because it is too large Load Diff

View File

@ -51,4 +51,49 @@ describe('description generation', () => {
});
});
});
expect.extend({
toBeSameAsFile(received: string, expectedPath: string) {
if (!fs.existsSync(expectedPath)) {
return {
message: () => `File ${expectedPath} was not found.`,
pass: false
};
}
const expected = fs.readFileSync(expectedPath).toString();
if (expected.replace(/\r\n/g, '\n') === received.replace(/\r\n/g, '\n')) {
return {
// This message is used in case of test negation `expect(a).not.toBeSameAsFile(f)`
message: () => `Identity check failed on ${expectedPath}.\nExpected:\n${expected}\n\nReceived:\n${received}`,
pass: true
};
} else {
const receivedPath = path.join(path.dirname(expectedPath), 'received-' + path.basename(expectedPath));
fs.writeFileSync(receivedPath, received);
return {
message: () => `Identity check failed on ${expectedPath}.\nReceived file saved in ${receivedPath}`,
pass: false
};
}
}
});
test('generates description for active rules', () => {
return withTestDir(async (dstPath) => {
generateRulesDescription(path.join(__dirname, 'resources', 'rules'), dstPath);
const rules = fs.readdirSync(dstPath);
expect(rules.length).toEqual(4);
let treated = 0;
rules.forEach(ruleDir => {
const languages = fs.readdirSync(`${dstPath}/${ruleDir}`);
expect(languages.length).toBeGreaterThanOrEqual(1);
languages.forEach(file => {
const actual = fs.readFileSync(`${dstPath}/${ruleDir}/${file}`).toString();
const expectedPath = path.join(__dirname, 'resources', 'metadata', ruleDir, file);
expect(actual).toBeSameAsFile(expectedPath);
treated++;
})
});
expect(treated).toBe(11);
});
});
});

View File

@ -4,7 +4,7 @@ import Git from 'nodegit';
import 'setimmediate';
jest.mock('@octokit/rest', () => {
let mockModule = {Octokit: function() {
return {Octokit: function() {
this.rest = {pulls: {list: jest.fn(() => {
return { data: [
{ title: 'Irrelevant S832' },
@ -19,7 +19,6 @@ jest.mock('@octokit/rest', () => {
] }
})}};
}};
return mockModule;
});
beforeEach(() => {

View File

@ -1,21 +1,26 @@
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>An unnamed namespace will be unique within each translation unit. Any declarations appearing in an unnamed namespace in a header will refer to a different entity in each translation unit, which is probably not the expected behavior.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>// Header.hpp
<pre class="highlight"><code class="language-cpp" data-lang="cpp">// Header.hpp
namespace // Noncompliant
{
extern int32_t x;
}</pre>
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>// File1.cpp
<pre class="highlight"><code class="language-cpp" data-lang="cpp">// File1.cpp
#include "Header.hpp"
namespace
@ -26,12 +31,12 @@ namespace
void fn_a(void)
{
x = 42;
}</pre>
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>// File2.cpp
<pre class="highlight"><code class="language-cpp" data-lang="cpp">// File2.cpp
#include "Header.hpp"
namespace
@ -45,9 +50,12 @@ void fn_b(void)
if (x == 42) // But does not, as there are 2 distinct "x" variables
{
}
}</pre>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Mentioning S987 here for testing purposes.</p>
</div>
</div>
</div>
<div class="sect1">
@ -63,8 +71,8 @@ void fn_b(void)
</li>
</ul>
</div>
<hr/>
</div>
Mentioning S987 here for testing purposes.
</div>
<div class="sect1">
<h2 id="_comments_and_links">Comments And Links</h2>
@ -82,4 +90,4 @@ Mentioning S987 here for testing purposes.
</div>
</div>
</div>
</div>
</div>

View File

@ -1,21 +1,26 @@
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>An unnamed namespace will be unique within each translation unit. Any declarations appearing in an unnamed namespace in a header will refer to a different entity in each translation unit, which is probably not the expected behavior.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>// Header.hpp
<pre class="highlight"><code class="language-cpp" data-lang="cpp">// Header.hpp
namespace // Noncompliant
{
extern int32_t x;
}</pre>
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>// File1.cpp
<pre class="highlight"><code class="language-cpp" data-lang="cpp">// File1.cpp
#include "Header.hpp"
namespace
@ -26,12 +31,12 @@ namespace
void fn_a(void)
{
x = 42;
}</pre>
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>// File2.cpp
<pre class="highlight"><code class="language-cpp" data-lang="cpp">// File2.cpp
#include "Header.hpp"
namespace
@ -45,11 +50,13 @@ void fn_b(void)
if (x == 42) // But does not, as there are 2 distinct "x" variables
{
}
}</pre>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Mentioning S987 here for testing purposes.</p>
</div>
</div>
Mentioning S987 here for testing purposes.
</div>
<div class="sect1">
<h2 id="_see">See</h2>
@ -83,4 +90,4 @@ Mentioning S987 here for testing purposes.
</div>
</div>
</div>
</div>
</div>

View File

@ -1,21 +1,97 @@
<p>Because <code>printf</code> format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that result
in the wrong strings being created. This rule statically validates the correlation of <code>printf</code> format strings to their arguments.</p>
<p>The related rule {rule:cpp:S2275} is about errors that will create undefined behavior, while this rule is about errors that produce an unexpected
string.</p>
<h2>Noncompliant Code Example</h2>
<pre>
printf("%d", 1, 2); // Noncompliant; the second argument "2" is unused
printf("%0-f", 1.2); // Noncompliant; flag "0" is ignored because of "-"
</pre>
<h2>Compliant Solution</h2>
<pre>
printf("%d %d", 1, 2); // Compliant
printf("%-f", 1.2); // Compliant
</pre>
<h2>Exceptions</h2>
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Because <code>printf</code> format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that result in the wrong strings being created. This rule statically validates the correlation of <code>printf</code> format strings to their arguments.</p>
</div>
<div class="paragraph">
<p>The related rule S2275 is about errors that will create undefined behavior, while this rule is about errors that produce an unexpected string.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-cpp" data-lang="cpp">printf("%d", 1, 2); // Noncompliant; the second argument "2" is unused
printf("%0-f", 1.2); // Noncompliant; flag "0" is ignored because of "-"</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_compliant_solution">Compliant Solution</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-cpp" data-lang="cpp">printf("%d %d", 1, 2); // Compliant
printf("%-f", 1.2); // Compliant</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_exceptions">Exceptions</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This rule will only work if the format string is provided as a string literal.</p>
<h2>See</h2>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_see">See</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li> <a href="https://wiki.sei.cmu.edu/confluence/x/J9YxBQ">CERT, FIO47-C.</a> - Use valid format strings </li>
<li>
<p><a href="https://wiki.sei.cmu.edu/confluence/x/J9YxBQ">CERT, FIO47-C.</a> - Use valid format strings</p>
</li>
</ul>
</div>
<hr/>
</div>
</div>
<div class="sect1">
<h2 id="_implementation_specification">Implementation Specification</h2>
<div class="sectionbody">
<div class="paragraph">
<p>(visible only on this page)</p>
</div>
<div class="sect2">
<h3 id="_message">Message</h3>
<div class="paragraph">
<p>XXXX</p>
</div>
<hr/>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_comments_and_links">Comments And Links</h2>
<div class="sectionbody">
<div class="paragraph">
<p>(visible only on this page)</p>
</div>
<div class="sect2">
<h3 id="_is_duplicated_by_s3941">is duplicated by: S3941</h3>
</div>
<div class="sect2">
<h3 id="_is_related_to_s2275">is related to: S2275</h3>
</div>
<div class="sect2">
<h3 id="_on_10_dec_2015_090759_tamas_vajk_wrote">on 10 Dec 2015, 09:07:59 Tamas Vajk wrote:</h3>
<div class="paragraph">
<p>\[~ann.campbell.2] Removed the performance label, as the performance impact is insignificant.</p>
</div>
</div>
<div class="sect2">
<h3 id="_on_10_dec_2015_144405_ann_campbell_wrote">on 10 Dec 2015, 14:44:05 Ann Campbell wrote:</h3>
<div class="paragraph">
<p>I&#8217;ve updated SQALE characteristic to match [~tamas.vajk]</p>
</div>
</div>
</div>
</div>

View File

@ -1,41 +1,114 @@
<p>Because composite format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that lead to unexpected
behaviors or runtime errors. This rule statically validates the good behavior of composite formats when calling the methods of
<code>String.Format</code>, <code>StringBuilder.AppendFormat</code>, <code>Console.Write</code>, <code>Console.WriteLine</code>,
<code>TextWriter.Write</code>, <code>TextWriter.WriteLine</code>, <code>Debug.WriteLine(String,Object[])</code>,
<code>Trace.TraceError(String,Object[])</code>, <code>Trace.TraceInformation(String,Object[])</code>,
<code>Trace.TraceWarning(String,Object[])</code> and <code>TraceSource.TraceInformation(String,Object[])</code>. </p>
<h2>Noncompliant Code Example</h2>
<pre>
s = string.Format("{0}", arg0, arg1); // Noncompliant, arg1 is declared but not used.
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Because composite format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that lead to unexpected behaviors or runtime errors. This rule statically validates the good behavior of composite formats when calling the methods of <code>String.Format</code>, <code>StringBuilder.AppendFormat</code>, <code>Console.Write</code>, <code>Console.WriteLine</code>, <code>TextWriter.Write</code>, <code>TextWriter.WriteLine</code>, <code>Debug.WriteLine(String,Object[])</code>, <code>Trace.TraceError(String,Object[])</code>, <code>Trace.TraceInformation(String,Object[])</code>, <code>Trace.TraceWarning(String,Object[])</code> and <code>TraceSource.TraceInformation(String,Object[])</code>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-cs" data-lang="cs">s = string.Format("{0}", arg0, arg1); // Noncompliant, arg1 is declared but not used.
s = string.Format("{0} {2}", arg0, arg1, arg2); // Noncompliant, the format item with index 1 is missing so arg1 will not be used.
s = string.Format("foo"); // Noncompliant, there is no need to use string.Format here.
</pre>
<h2>Compliant Solution</h2>
<pre>
s = string.Format("{0}", arg0);
s = string.Format("foo"); // Noncompliant, there is no need to use string.Format here.</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_compliant_solution">Compliant Solution</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-cs" data-lang="cs">s = string.Format("{0}", arg0);
s = string.Format("{0} {1}", arg0, arg2);
s = "foo";
</pre>
<h2>Exceptions</h2>
s = "foo";</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_exceptions">Exceptions</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li> No issue is raised if the format string is not a <code>const</code>. </li>
<li>
<p>No issue is raised if the format string is not a <code>const</code>.</p>
</li>
</ul>
<pre>
var pattern = "{0} {1} {2}";
var res = string.Format(pattern, 1, 2); // Compliant, not const string are not recognized
</pre>
</div>
<div class="listingblock">
<div class="content">
<pre>var pattern = "{0} {1} {2}";
var res = string.Format(pattern, 1, 2); // Compliant, not const string are not recognized</pre>
</div>
</div>
<div class="ulist">
<ul>
<li> No issue is raised if the argument is not an inline creation array. </li>
<li>
<p>No issue is raised if the argument is not an inline creation array.</p>
</li>
</ul>
<pre>
var array = new int[] {};
var res = string.Format("{0} {1}", array); // Compliant we don't know the size of the array
</pre>
</div>
<div class="listingblock">
<div class="content">
<pre>var array = new int[] {};
var res = string.Format("{0} {1}", array); // Compliant we don't know the size of the array</pre>
</div>
</div>
<div class="ulist">
<ul>
<li> This rule doesn't check whether the format specifier (defined after the <code>:</code>) is actually valid. </li>
</ul>
<h2>See</h2>
<ul>
<li> <a href="https://wiki.sei.cmu.edu/confluence/x/J9YxBQ">CERT, FIO47-C.</a> - Use valid format strings </li>
<li>
<p>This rule doesn&#8217;t check whether the format specifier (defined after the <code>:</code>) is actually valid.</p>
</li>
</ul>
</div>
<hr/>
</div>
</div>
<div class="sect1">
<h2 id="_implementation_specification">Implementation Specification</h2>
<div class="sectionbody">
<div class="paragraph">
<p>(visible only on this page)</p>
</div>
<div class="sect2">
<h3 id="_message">Message</h3>
<div class="paragraph">
<p>XXXX</p>
</div>
<hr/>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_comments_and_links">Comments And Links</h2>
<div class="sectionbody">
<div class="paragraph">
<p>(visible only on this page)</p>
</div>
<div class="sect2">
<h3 id="_is_duplicated_by_s3941">is duplicated by: S3941</h3>
</div>
<div class="sect2">
<h3 id="_is_related_to_s2275">is related to: S2275</h3>
</div>
<div class="sect2">
<h3 id="_on_10_dec_2015_090759_tamas_vajk_wrote">on 10 Dec 2015, 09:07:59 Tamas Vajk wrote:</h3>
<div class="paragraph">
<p>\[~ann.campbell.2] Removed the performance label, as the performance impact is insignificant.</p>
</div>
</div>
<div class="sect2">
<h3 id="_on_10_dec_2015_144405_ann_campbell_wrote">on 10 Dec 2015, 14:44:05 Ann Campbell wrote:</h3>
<div class="paragraph">
<p>I&#8217;ve updated SQALE characteristic to match [~tamas.vajk]</p>
</div>
</div>
</div>
</div>

View File

@ -1,16 +1,21 @@
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Because <code>printf</code> format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that result in the wrong strings being created. This rule statically validates the correlation of <code>printf</code> format strings to their arguments.</p>
</div>
<div class="paragraph">
<p>The related rule S2275 is about errors that will create undefined behavior, while this rule is about errors that produce an unexpected string.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>printf("%d", 1, 2); // Noncompliant; the second argument "2" is unused
printf("%0-f", 1.2); // Noncompliant; flag "0" is ignored because of "-"</pre>
<pre class="highlight"><code class="language-cpp" data-lang="cpp">printf("%d", 1, 2); // Noncompliant; the second argument "2" is unused
printf("%0-f", 1.2); // Noncompliant; flag "0" is ignored because of "-"</code></pre>
</div>
</div>
</div>
@ -20,8 +25,8 @@ printf("%0-f", 1.2); // Noncompliant; flag "0" is ignored because of "-"</pre>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>printf("%d %d", 1, 2); // Compliant
printf("%-f", 1.2); // Compliant</pre>
<pre class="highlight"><code class="language-cpp" data-lang="cpp">printf("%d %d", 1, 2); // Compliant
printf("%-f", 1.2); // Compliant</code></pre>
</div>
</div>
</div>

View File

@ -1,11 +1,17 @@
<p>Because <code>printf</code>-style format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that
result in the wrong strings being created. This rule statically validates the correlation of <code>printf</code>-style format strings to their
arguments when calling the <code>format(...)</code> methods of <code>java.util.Formatter</code>, <code>java.lang.String</code>,
<code>java.io.PrintStream</code>, <code>MessageFormat</code>, and <code>java.io.PrintWriter</code> classes and the <code>printf(...)</code> methods of
<code>java.io.PrintStream</code> or <code>java.io.PrintWriter</code> classes. </p>
<h2>Noncompliant Code Example</h2>
<pre>
String.format("First {0} and then {1}", "foo", "bar"); //Noncompliant. Looks like there is a confusion with the use of {{java.text.MessageFormat}}, parameters "foo" and "bar" will be simply ignored here
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Because <code>printf</code>-style format strings are interpreted at runtime, rather than validated by the compiler, they can contain errors that result in the wrong strings being created. This rule statically validates the correlation of <code>printf</code>-style format strings to their arguments when calling the <code>format(...)</code> methods of <code>java.util.Formatter</code>, <code>java.lang.String</code>, <code>java.io.PrintStream</code>, <code>MessageFormat</code>, and <code>java.io.PrintWriter</code> classes and the <code>printf(...)</code> methods of <code>java.io.PrintStream</code> or <code>java.io.PrintWriter</code> classes.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>String.format("First {0} and then {1}", "foo", "bar"); //Noncompliant. Looks like there is a confusion with the use of {{java.text.MessageFormat}}, parameters "foo" and "bar" will be simply ignored here
String.format("Display %3$d and then %d", 1, 2, 3); //Noncompliant; the second argument '2' is unused
String.format("Too many arguments %d and %d", 1, 2, 3); //Noncompliant; the third argument '3' is unused
String.format("First Line\n"); //Noncompliant; %n should be used in place of \n to produce the platform-specific line separator
@ -30,11 +36,17 @@ slf4jLog.debug(marker, "message {}");
slf4jLog.debug(marker, "message", 1); // Noncompliant - String contains no format specifiers.
org.apache.logging.log4j.Logger log4jLog;
log4jLog.debug("message", 1); // Noncompliant - String contains no format specifiers.
</pre>
<h2>Compliant Solution</h2>
<pre>
String.format("First %s and then %s", "foo", "bar");
log4jLog.debug("message", 1); // Noncompliant - String contains no format specifiers.</pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_compliant_solution">Compliant Solution</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>String.format("First %s and then %s", "foo", "bar");
String.format("Display %2$d and then %d", 1, 3);
String.format("Too many arguments %d %d", 1, 2);
String.format("First Line%n");
@ -58,10 +70,64 @@ slf4jLog.debug(marker, "message {}");
slf4jLog.debug(marker, "message {}", 1);
org.apache.logging.log4j.Logger log4jLog;
log4jLog.debug("message {}", 1);
</pre>
<h2>See</h2>
log4jLog.debug("message {}", 1);</pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_see">See</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li> <a href="https://wiki.sei.cmu.edu/confluence/x/J9YxBQ">CERT, FIO47-C.</a> - Use valid format strings </li>
<li>
<p><a href="https://wiki.sei.cmu.edu/confluence/x/J9YxBQ">CERT, FIO47-C.</a> - Use valid format strings</p>
</li>
</ul>
</div>
<hr/>
</div>
</div>
<div class="sect1">
<h2 id="_implementation_specification">Implementation Specification</h2>
<div class="sectionbody">
<div class="paragraph">
<p>(visible only on this page)</p>
</div>
<div class="sect2">
<h3 id="_message">Message</h3>
<div class="paragraph">
<p>XXXX</p>
</div>
<hr/>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_comments_and_links">Comments And Links</h2>
<div class="sectionbody">
<div class="paragraph">
<p>(visible only on this page)</p>
</div>
<div class="sect2">
<h3 id="_is_duplicated_by_s3941">is duplicated by: S3941</h3>
</div>
<div class="sect2">
<h3 id="_is_related_to_s2275">is related to: S2275</h3>
</div>
<div class="sect2">
<h3 id="_on_10_dec_2015_090759_tamas_vajk_wrote">on 10 Dec 2015, 09:07:59 Tamas Vajk wrote:</h3>
<div class="paragraph">
<p>\[~ann.campbell.2] Removed the performance label, as the performance impact is insignificant.</p>
</div>
</div>
<div class="sect2">
<h3 id="_on_10_dec_2015_144405_ann_campbell_wrote">on 10 Dec 2015, 14:44:05 Ann Campbell wrote:</h3>
<div class="paragraph">
<p>I&#8217;ve updated SQALE characteristic to match [~tamas.vajk]</p>
</div>
</div>
</div>
</div>

View File

@ -1,20 +1,45 @@
<p>Formatting strings, either with the <code>%</code> operator or <code>str.format</code> method, requires a valid string and arguments matching this
string's replacement fields.</p>
<p>This also applies to loggers from the <code>logging</code> module. Internally they use <code>%-formatting</code>. The only difference is that they
will log an error instead of raising an exception when provided arguments are invalid.</p>
<p>Formatted string literals, also called "f-strings", are generally simpler to use, and any syntax mistake will fail at compile time. However it is
easy to forget curly braces and it won't raise any error.</p>
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Formatting strings, either with the <code>%</code> operator or <code>str.format</code> method, requires a valid string and arguments matching this string&#8217;s replacement fields.</p>
</div>
<div class="paragraph">
<p>This also applies to loggers from the <code>logging</code> module. Internally they use <code>%-formatting</code>. The only difference is that they will log an error instead of raising an exception when provided arguments are invalid.</p>
</div>
<div class="paragraph">
<p>Formatted string literals, also called "f-strings", are generally simpler to use, and any syntax mistake will fail at compile time. However it is easy to forget curly braces and it won&#8217;t raise any error.</p>
</div>
<div class="paragraph">
<p>This rule raises an issue when:</p>
</div>
<div class="ulist">
<ul>
<li> A string formatted with <code>%</code> will not return the expected string because some arguments are not used. </li>
<li> A string formatted with <code>str.format</code> will not return the expected string because some arguments are not used. </li>
<li> An "f-string" doesn't contain any replacement field, which probably means that some curly braces are missing. </li>
<li> Loggers will log an error because their message is not formatted properly. </li>
<li>
<p>A string formatted with <code>%</code> will not return the expected string because some arguments are not used.</p>
</li>
<li>
<p>A string formatted with <code>str.format</code> will not return the expected string because some arguments are not used.</p>
</li>
<li>
<p>An "f-string" doesn&#8217;t contain any replacement field, which probably means that some curly braces are missing.</p>
</li>
<li>
<p>Loggers will log an error because their message is not formatted properly.</p>
</li>
</ul>
<p>Rule {rule:python:S2275} covers cases where formatting a string will raise an exception.</p>
<h2>Noncompliant Code Example</h2>
<pre>
"Error %(message)s" % {"message": "something failed", "extra": "some dead code"} # Noncompliant. Remove the unused argument "extra" or add a replacement field.
</div>
<div class="paragraph">
<p>Rule S2275 covers cases where formatting a string will raise an exception.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-python" data-lang="python">"Error %(message)s" % {"message": "something failed", "extra": "some dead code"} # Noncompliant. Remove the unused argument "extra" or add a replacement field.
"Error: User {} has not been able to access []".format("Alice", "MyFile") # Noncompliant. Remove 1 unexpected argument or add a replacement field.
@ -23,11 +48,17 @@ resource = "MyFile"
message = f"Error: User [user] has not been able to access [resource]" # Noncompliant. Add replacement fields or use a normal string instead of an f-string.
import logging
logging.error("Error: User %s has not been able to access %s", "Alice") # Noncompliant. Add 1 missing argument.
</pre>
<h2>Compliant Solution</h2>
<pre>
"Error %(message)s" % {"message": "something failed"}
logging.error("Error: User %s has not been able to access %s", "Alice") # Noncompliant. Add 1 missing argument.</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_compliant_solution">Compliant Solution</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-python" data-lang="python">"Error %(message)s" % {"message": "something failed"}
"Error: User {} has not been able to access {}".format("Alice", "MyFile")
@ -36,17 +67,122 @@ resource = "MyFile"
message = f"Error: User {user} has not been able to access {resource}"
import logging
logging.error("Error: User %s has not been able to access %s", "Alice", "MyFile")
</pre>
<h2>See</h2>
logging.error("Error: User %s has not been able to access %s", "Alice", "MyFile")</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_see">See</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li> <a href="https://docs.python.org/3/library/string.html#format-string-syntax">Python documentation - Format String Syntax</a> </li>
<li> <a href="https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting">Python documentation - printf-style String
Formatting</a> </li>
<li> <a href="https://docs.python.org/3/howto/logging.html#loggers">Python documentation - Loggers</a> </li>
<li> <a href="https://docs.python.org/3/howto/logging-cookbook.html#using-particular-formatting-styles-throughout-your-application">Python
documentation - Using particular formatting styles throughout your application</a> </li>
<li> <a href="https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literals">Python documentation - Formatted string
literals</a> </li>
<li>
<p><a href="https://docs.python.org/3/library/string.html#format-string-syntax">Python documentation - Format String Syntax</a></p>
</li>
<li>
<p><a href="https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting">Python documentation - printf-style String Formatting</a></p>
</li>
<li>
<p><a href="https://docs.python.org/3/howto/logging.html#loggers">Python documentation - Loggers</a></p>
</li>
<li>
<p><a href="https://docs.python.org/3/howto/logging-cookbook.html#using-particular-formatting-styles-throughout-your-application">Python documentation - Using particular formatting styles throughout your application</a></p>
</li>
<li>
<p><a href="https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literals">Python documentation - Formatted string literals</a></p>
</li>
</ul>
</div>
<hr/>
</div>
</div>
<div class="sect1">
<h2 id="_implementation_specification">Implementation Specification</h2>
<div class="sectionbody">
<div class="paragraph">
<p>(visible only on this page)</p>
</div>
<div class="sect2">
<h3 id="_message">Message</h3>
<div class="ulist">
<ul>
<li>
<p>Add replacement fields or use a normal string instead of an f-string.</p>
</li>
<li>
<p>Remove this unused argument.</p>
</li>
<li>
<p>Remove X unused positional arguments.</p>
</li>
<li>
<p>Fix this formatted string&#8217;s syntax.</p>
</li>
<li>
<p>Name unnamed replacement field(s).</p>
</li>
<li>
<p>Replace formatting argument(s) with a mapping; Replacement fields are named.</p>
</li>
<li>
<p>Use only positional or named fields, don&#8217;t mix them.</p>
</li>
<li>
<p>Replace this value with a number as "%d" requires.</p>
</li>
<li>
<p>Replace this value with an integer as "%X" requires.</p>
</li>
<li>
<p>Replace this value with an integer as "*" requires.</p>
</li>
<li>
<p>Add X missing argument(s).</p>
</li>
<li>
<p>Remove X unexpected argument(s); format string expects Y arguments.</p>
</li>
<li>
<p>Replace this key; %-format accepts only string keys.</p>
</li>
<li>
<p>Provide a value for field "X".</p>
</li>
<li>
<p>Remove this unused argument or add a replacement field.</p>
</li>
</ul>
</div>
<hr/>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_comments_and_links">Comments And Links</h2>
<div class="sectionbody">
<div class="paragraph">
<p>(visible only on this page)</p>
</div>
<div class="sect2">
<h3 id="_is_duplicated_by_s3941">is duplicated by: S3941</h3>
</div>
<div class="sect2">
<h3 id="_is_related_to_s2275">is related to: S2275</h3>
</div>
<div class="sect2">
<h3 id="_on_10_dec_2015_090759_tamas_vajk_wrote">on 10 Dec 2015, 09:07:59 Tamas Vajk wrote:</h3>
<div class="paragraph">
<p>\[~ann.campbell.2] Removed the performance label, as the performance impact is insignificant.</p>
</div>
</div>
<div class="sect2">
<h3 id="_on_10_dec_2015_144405_ann_campbell_wrote">on 10 Dec 2015, 14:44:05 Ann Campbell wrote:</h3>
<div class="paragraph">
<p>I&#8217;ve updated SQALE characteristic to match [~tamas.vajk]</p>
</div>
</div>
</div>
</div>

View File

@ -1,12 +1,55 @@
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Signal handling contains implementation-defined and undefined behavior.</p>
<h2>Noncompliant Code Example</h2>
<pre>
#include &lt;signal.h&gt; /* Noncompliant */
</pre>
Mentioning S1000 here for testing purposes.
<h2>See</h2>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-cpp" data-lang="cpp">#include &lt;signal.h&gt; /* Noncompliant */</code></pre>
</div>
</div>
<div class="paragraph">
<p>Mentioning S1000 here for testing purposes.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_see">See</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li> MISRA C:2004, 20.8 - The signal handling facilities of &lt;signal.h&gt; shall not be used. </li>
<li> MISRA C:2012, 21.5 - The standard header file &lt;signal.h&gt; shall not be used </li>
<li>
<p>MISRA C:2004, 20.8 - The signal handling facilities of &lt;signal.h&gt; shall not be used.</p>
</li>
<li>
<p>MISRA C:2012, 21.5 - The standard header file &lt;signal.h&gt; shall not be used</p>
</li>
</ul>
</div>
<hr/>
</div>
</div>
<div class="sect1">
<h2 id="_comments_and_links">Comments And Links</h2>
<div class="sectionbody">
<div class="paragraph">
<p>(visible only on this page)</p>
</div>
<div class="sect2">
<h3 id="_is_related_to_s1054">is related to: S1054</h3>
</div>
<div class="sect2">
<h3 id="_on_31_mar_2015_190723_evgeny_mandrikov_wrote">on 31 Mar 2015, 19:07:23 Evgeny Mandrikov wrote:</h3>
<div class="paragraph">
<p>\[~ann.campbell.2] implementation seems more complete (SQALE, description) than this spec.</p>
</div>
</div>
</div>
</div>

View File

@ -1,15 +1,22 @@
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Signal handling contains implementation-defined and undefined behavior.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>#include &lt;signal.h&gt; /* Noncompliant */</pre>
<pre class="highlight"><code class="language-cpp" data-lang="cpp">#include &lt;signal.h&gt; /* Noncompliant */</code></pre>
</div>
</div>
Mentioning S1000 here for testing purposes.
<div class="paragraph">
<p>Mentioning S1000 here for testing purposes.</p>
</div>
</div>
</div>
<div class="sect1">
@ -45,4 +52,4 @@ Mentioning S1000 here for testing purposes.
</div>
</div>
</div>
</div>
</div>

View File

@ -3,6 +3,7 @@ An unnamed namespace will be unique within each translation unit. Any declaratio
== Noncompliant Code Example
[source,cpp]
----
// Header.hpp
namespace // Noncompliant
@ -11,6 +12,7 @@ namespace // Noncompliant
}
----
[source,cpp]
----
// File1.cpp
#include "Header.hpp"
@ -26,6 +28,7 @@ void fn_a(void)
}
----
[source,cpp]
----
// File2.cpp
#include "Header.hpp"

View File

@ -5,6 +5,7 @@ The related rule S2275 is about errors that will create undefined behavior, whil
== Noncompliant Code Example
[source,cpp]
----
printf("%d", 1, 2); // Noncompliant; the second argument "2" is unused
printf("%0-f", 1.2); // Noncompliant; flag "0" is ignored because of "-"
@ -12,6 +13,7 @@ printf("%0-f", 1.2); // Noncompliant; flag "0" is ignored because of "-"
== Compliant Solution
[source,cpp]
----
printf("%d %d", 1, 2); // Compliant
printf("%-f", 1.2); // Compliant

View File

@ -2,6 +2,7 @@ Because composite format strings are interpreted at runtime, rather than validat
== Noncompliant Code Example
[source,cs]
----
s = string.Format("{0}", arg0, arg1); // Noncompliant, arg1 is declared but not used.
s = string.Format("{0} {2}", arg0, arg1, arg2); // Noncompliant, the format item with index 1 is missing so arg1 will not be used.
@ -10,6 +11,7 @@ s = string.Format("foo"); // Noncompliant, there is no need to use string.Format
== Compliant Solution
[source,cs]
----
s = string.Format("{0}", arg0);
s = string.Format("{0} {1}", arg0, arg2);

View File

@ -18,6 +18,7 @@ Rule S2275 covers cases where formatting a string will raise an exception.
== Noncompliant Code Example
[source,python]
----
"Error %(message)s" % {"message": "something failed", "extra": "some dead code"} # Noncompliant. Remove the unused argument "extra" or add a replacement field.
@ -33,6 +34,7 @@ logging.error("Error: User %s has not been able to access %s", "Alice") # Nonco
== Compliant Solution
[source,python]
----
"Error %(message)s" % {"message": "something failed"}

View File

@ -3,6 +3,7 @@ Signal handling contains implementation-defined and undefined behavior.
== Noncompliant Code Example
[source,cpp]
----
#include <signal.h> /* Noncompliant */
----

View File

@ -5,12 +5,16 @@ FIXME: add a description
== Noncompliant Code Example
// Replace text with the language you are using if relevant
[source,text]
----
FIXME
----
== Compliant Solution
// Replace text with the language you are using if relevant
[source,text]
----
FIXME
----

View File

@ -5,12 +5,16 @@ FIXME: add a description
== Noncompliant Code Example
// Replace text with the language you are using if relevant
[source,text]
----
FIXME
----
== Compliant Solution
// Replace text with the language you are using if relevant
[source,text]
----
FIXME
----

View File

@ -6,9 +6,9 @@ import click
from rspec_tools.checklinks import check_html_links
from rspec_tools.errors import RuleNotFoundError, RuleValidationError
from rspec_tools.create_rule import create_new_rule, add_language_to_rule
from rspec_tools.rules import RulesRepository
from rspec_tools.rules import RulesRepository, LanguageSpecificRule
from rspec_tools.validation.metadata import validate_rule_metadata
from rspec_tools.validation.description import validate_section_names, validate_section_levels, validate_parameters
from rspec_tools.validation.description import validate_section_names, validate_section_levels, validate_parameters, validate_source_language
from rspec_tools.coverage import update_coverage_for_all_repos, update_coverage_for_repo, update_coverage_for_repo_version
from rspec_tools.notify_failure_on_slack import notify_slack
@ -67,6 +67,22 @@ def validate_rules_metadata(rules):
if error_counter > 0:
fatal_error(f"Validation failed due to {error_counter} errors out of {len(rules)} analyzed rules")
VALIDATORS = [validate_section_names,
validate_section_levels,
validate_parameters,
validate_source_language,
]
def validate_rule_specialization(lang_spec_rule: LanguageSpecificRule):
error_counter = 0
for validator in VALIDATORS:
try:
validator(lang_spec_rule)
except RuleValidationError as e:
click.echo(e.message, err=True)
error_counter += 1
return error_counter
@cli.command()
@click.option('--d', required=True)
@click.argument('rules', nargs=-1)
@ -79,21 +95,7 @@ def check_description(d, rules):
if rules and rule.id not in rules:
continue
for lang_spec_rule in rule.specializations:
try:
validate_section_names(lang_spec_rule)
except RuleValidationError as e:
click.echo(e.message, err=True)
error_counter += 1
try:
validate_section_levels(lang_spec_rule)
except RuleValidationError as e:
click.echo(e.message, err=True)
error_counter += 1
try:
validate_parameters(lang_spec_rule)
except RuleValidationError as e:
click.echo(e.message, err=True)
error_counter += 1
error_counter += validate_rule_specialization(lang_spec_rule)
if error_counter > 0:
fatal_error(f"Validation failed due to {error_counter} errors")

View File

@ -1,4 +1,3 @@
import json
from bs4 import BeautifulSoup
from pathlib import Path
from typing import Final
@ -47,3 +46,61 @@ def validate_parameters(rule_language: LanguageSpecificRule):
if child.name is None or child == h3 or child.name == 'hr':
continue
validate_one_parameter(child, rule_language.id)
HIGHLIGHTED_LANGUAGES = {
# languages with syntax coloring in highlight.js
'abap': 'abap',
'cfamily': 'cpp',
'csharp': 'csharp',
'css': 'css',
'go': 'go',
'html': 'html',
'java': 'java',
'javascript': 'javascript',
'kotlin': 'kotlin',
'php': 'php',
'plsql': 'sql',
'python': 'python',
'ruby': 'ruby',
'rust': 'rust',
'scala': 'scala',
'swift': 'swift',
'terraform': 'terraform',
'tsql': 'sql',
'vbnet': 'vbnet',
'xml': 'xml',
'c': 'c',
'objectivec': 'objectivec',
'vb': 'vb',
# these languages are not supported by highlight.js as the moment:
'apex': 'apex',
'cloudformation': 'cloudformation',
'cobol': 'cobol',
'flex': 'flex',
'pli': 'pli',
'rpg': 'rpg',
'text': 'text',
'vb6': 'vb6'
}
def highlight_name(rule_language: LanguageSpecificRule):
if (rule_language.language in HIGHLIGHTED_LANGUAGES):
return HIGHLIGHTED_LANGUAGES[rule_language.language]
return rule_language.language
def known_highlight(language):
return language in HIGHLIGHTED_LANGUAGES.values()
def validate_source_language(rule_language: LanguageSpecificRule):
descr = rule_language.description
for h2 in descr.findAll('h2'):
name = h2.text.strip()
if name.startswith('Compliant') or name.startswith('Noncompliant'):
for pre in h2.parent.find_all('pre'):
if not pre.has_attr('class') or pre['class'][0] != u'highlight' or not pre.code or not pre.code.has_attr('data-lang'):
raise RuleValidationError(f'''Rule {rule_language.id} has non highlighted code example in section "{name}".
Use [source,{highlight_name(rule_language)}] or [source,text] before the opening '----'.''')
elif not known_highlight(pre.code['data-lang']):
raise RuleValidationError(f'''Rule {rule_language.id} has unknown language "{pre.code['data-lang']}" in code example in section "{name}".
Are you looking for "{highlight_name(rule_language)}"?''')

View File

@ -12,6 +12,8 @@ With default provided regular expression: ``++^[a-z][a-zA-Z0-9]*$++``:
void DoSomething (void);
----
== See
=== Parameters
*format*: STRING [ `+^([A-Z0-9_]*|[a-z0-9_]*)$+` ]

View File

@ -8,10 +8,13 @@ Shared naming conventions allow teams to collaborate efficiently. This rule chec
With default provided regular expression: ``++^[a-z][a-zA-Z0-9]*$++``:
[source, unknown]
----
void DoSomething (void);
----
== See
=== Parameters
****

View File

@ -19,9 +19,14 @@
</div>
<div class="listingblock">
<div class="content">
<pre>void DoSomething (void);</pre>
<pre class="highlight"><code class="language-unknown" data-lang="unknown">void DoSomething (void);</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_see">See</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_parameters">Parameters</h3>
<div class="sidebarblock">

View File

@ -8,10 +8,17 @@ Shared naming conventions allow teams to collaborate efficiently. This rule chec
With default provided regular expression: ``++^[a-z][a-zA-Z0-9]*$++``:
[source, java]
----
void DoSomething (void);
----
----
void DoSomethingElse (void);
----
== See
=== Parameters
.format

View File

@ -19,9 +19,19 @@
</div>
<div class="listingblock">
<div class="content">
<pre>void DoSomething (void);</pre>
<pre class="highlight"><code class="language-java" data-lang="java">void DoSomething (void);</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre>void DoSomethingElse (void);</pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_see">See</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_parameters">Parameters</h3>
<div class="sidebarblock">

View File

@ -4,6 +4,7 @@ include::../description.adoc[]
With default provided regular expression ``++^([A-Z0-9_]*|[a-z0-9_]*)$++``:
[source,abap]
----
METHOD MyMethod
...
@ -12,6 +13,7 @@ ENDMETHOD.
== Compliant Solution
[source,abap]
----
METHOD MY_METHOD
...

View File

@ -9,9 +9,9 @@
</div>
<div class="listingblock">
<div class="content">
<pre>METHOD MyMethod
<pre class="highlight"><code class="language-abap" data-lang="abap">METHOD MyMethod
...
ENDMETHOD.</pre>
ENDMETHOD.</code></pre>
</div>
</div>
</div>
@ -21,9 +21,9 @@ ENDMETHOD.</pre>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>METHOD MY_METHOD
<pre class="highlight"><code class="language-abap" data-lang="abap">METHOD MY_METHOD
...
ENDMETHOD.</pre>
ENDMETHOD.</code></pre>
</div>
</div>
</div>

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With provided regular expression ``++^[a-z][a-zA-Z0-9_]*$++``:
[source,apex]
----
public void DoSomething(){...}
----
== Compliant Solution
[source,apex]
----
public void doSomething(){...}
----

View File

@ -9,7 +9,7 @@
</div>
<div class="listingblock">
<div class="content">
<pre>public void DoSomething(){...}</pre>
<pre class="highlight"><code class="language-apex" data-lang="apex">public void DoSomething(){...}</code></pre>
</div>
</div>
</div>
@ -19,7 +19,7 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>public void doSomething(){...}</pre>
<pre class="highlight"><code class="language-apex" data-lang="apex">public void doSomething(){...}</code></pre>
</div>
</div>
</div>

View File

@ -4,16 +4,20 @@ include::../description.adoc[]
With default provided regular expression: ``++^[a-z][a-zA-Z0-9]*$++``:
[source,cpp]
----
void DoSomething (void);
----
== Compliant Solution
[source,text]
----
void doSomething (void);
----
== See
=== Parameters
.format

View File

@ -9,7 +9,7 @@
</div>
<div class="listingblock">
<div class="content">
<pre>void DoSomething (void);</pre>
<pre class="highlight"><code class="language-cpp" data-lang="cpp">void DoSomething (void);</code></pre>
</div>
</div>
</div>
@ -19,9 +19,14 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>void doSomething (void);</pre>
<pre class="highlight"><code class="language-text" data-lang="text">void doSomething (void);</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_see">See</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_parameters">Parameters</h3>
<div class="sidebarblock">

View File

@ -2,15 +2,14 @@ Shared naming conventions allow teams to collaborate efficiently. This rule chec
== Noncompliant Code Example
[source, javascript]
----
public int doSomething() {...}
----
== Compliant Solution
----
public int DoSomething() {...}
----
Don't do anything
== Exceptions

View File

@ -6,7 +6,7 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>public int doSomething() {...}</pre>
<pre class="highlight"><code class="language-javascript" data-lang="javascript">public int doSomething() {...}</code></pre>
</div>
</div>
</div>
@ -14,10 +14,8 @@
<div class="sect1">
<h2 id="_compliant_solution">Compliant Solution</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>public int DoSomething() {...}</pre>
</div>
<div class="paragraph">
<p>Don&#8217;t do anything</p>
</div>
</div>
</div>

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With default provided regular expression: ^[a-z][a-zA-Z0-9]*$
[source,flex]
----
function DoSomething(){...}
----
== Compliant Solution
[source,flex]
----
function doSomething(){...}
----

View File

@ -9,7 +9,7 @@
</div>
<div class="listingblock">
<div class="content">
<pre>function DoSomething(){...}</pre>
<pre class="highlight"><code class="language-flex" data-lang="flex">function DoSomething(){...}</code></pre>
</div>
</div>
</div>
@ -19,7 +19,7 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>function doSomething(){...}</pre>
<pre class="highlight"><code class="language-flex" data-lang="flex">function doSomething(){...}</code></pre>
</div>
</div>
</div>

View File

@ -4,6 +4,7 @@ include::../description.adoc[]
With default provided regular expression: ``++^(_|[a-zA-Z0-9]+)$++``:
[source, go]
----
func execute_all() {
...
@ -12,6 +13,7 @@ func execute_all() {
== Compliant Solution
[source, go]
----
func executeAll() {
...

View File

@ -9,9 +9,9 @@
</div>
<div class="listingblock">
<div class="content">
<pre>func execute_all() {
<pre class="highlight"><code class="language-go" data-lang="go">func execute_all() {
...
}</pre>
}</code></pre>
</div>
</div>
</div>
@ -21,9 +21,9 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>func executeAll() {
<pre class="highlight"><code class="language-go" data-lang="go">func executeAll() {
...
}</pre>
}</code></pre>
</div>
</div>
</div>

View File

@ -4,12 +4,14 @@ Shared naming conventions allow teams to collaborate efficiently. This rule chec
With default provided regular expression ``++^[a-z][a-zA-Z0-9]*$++``:
[source, java]
----
public int DoSomething(){...}
----
== Compliant Solution
[source, java]
----
public int doSomething(){...}
----

View File

@ -9,7 +9,7 @@
</div>
<div class="listingblock">
<div class="content">
<pre>public int DoSomething(){...}</pre>
<pre class="highlight"><code class="language-java" data-lang="java">public int DoSomething(){...}</code></pre>
</div>
</div>
</div>
@ -19,7 +19,7 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>public int doSomething(){...}</pre>
<pre class="highlight"><code class="language-java" data-lang="java">public int doSomething(){...}</code></pre>
</div>
</div>
</div>

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With the default regular expression ``++^[a-z][a-zA-Z0-9]*$++``:
[source, javascript]
----
function DoSomething(){...} // Noncompliant
----
== Compliant Solution
[source, javascript]
----
function doSomething(){...}
----

View File

@ -9,7 +9,7 @@
</div>
<div class="listingblock">
<div class="content">
<pre>function DoSomething(){...} // Noncompliant</pre>
<pre class="highlight"><code class="language-javascript" data-lang="javascript">function DoSomething(){...} // Noncompliant</code></pre>
</div>
</div>
</div>
@ -19,7 +19,7 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>function doSomething(){...}</pre>
<pre class="highlight"><code class="language-javascript" data-lang="javascript">function doSomething(){...}</code></pre>
</div>
</div>
</div>

View File

@ -1,3 +1,16 @@
<div class="paragraph">
<p>Shared naming conventions allow teams to collaborate efficiently. This rule checks that all function names match a provided regular expression.</p>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="paragraph">
<p>With default provided regular expression <code>^[a-z][a-zA-Z0-9]*$</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">public int DoSomething(){...}</code></pre>
</div>
</div>
</div>
</div>

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With default provided regular expression: ``++^[a-z][a-zA-Z0-9]*$++``:
[source, php]
----
function DoSomething(){...}
----
== Compliant Solution
[source, php]
----
function doSomething(){...}
----

View File

@ -9,7 +9,7 @@
</div>
<div class="listingblock">
<div class="content">
<pre>function DoSomething(){...}</pre>
<pre class="highlight"><code class="language-php" data-lang="php">function DoSomething(){...}</code></pre>
</div>
</div>
</div>
@ -19,7 +19,7 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>function doSomething(){...}</pre>
<pre class="highlight"><code class="language-php" data-lang="php">function doSomething(){...}</code></pre>
</div>
</div>
</div>

View File

@ -4,6 +4,7 @@ Sharing some naming conventions is a key point to make it possible for a team to
With default provided regular expression: ``++^[a-z_][a-z0-9_]*$++``
[source, python]
----
class MyClass:
def MyMethod(a,b):
@ -12,6 +13,7 @@ class MyClass:
== Compliant Solution
[source, python]
----
class MyClass:
def my_method(a,b):

View File

@ -9,9 +9,9 @@
</div>
<div class="listingblock">
<div class="content">
<pre>class MyClass:
<pre class="highlight"><code class="language-python" data-lang="python">class MyClass:
def MyMethod(a,b):
...</pre>
...</code></pre>
</div>
</div>
</div>
@ -21,9 +21,9 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>class MyClass:
<pre class="highlight"><code class="language-python" data-lang="python">class MyClass:
def my_method(a,b):
...</pre>
...</code></pre>
</div>
</div>
</div>

View File

@ -4,12 +4,14 @@ Sharing some naming conventions is a key point to make it possible for a team to
With default provided regular expression ``++^SR[a-zA-Z0-9]*$++``:
[source,rpg]
----
C XXXXX BEGSR
...
C ENDSR
----
[source,rpg]
----
/free
begsr yyyy;
@ -19,12 +21,14 @@ C ENDSR
== Compliant Solution
[source,rpg]
----
C SR102 BEGSR
...
C ENDSR
----
[source,rpg]
----
/free
begsr SR103;

View File

@ -9,17 +9,17 @@
</div>
<div class="listingblock">
<div class="content">
<pre>C XXXXX BEGSR
<pre class="highlight"><code class="language-rpg" data-lang="rpg">C XXXXX BEGSR
...
C ENDSR</pre>
C ENDSR</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre> /free
<pre class="highlight"><code class="language-rpg" data-lang="rpg"> /free
begsr yyyy;
endsr;
/end-free{code}</pre>
/end-free{code}</code></pre>
</div>
</div>
</div>
@ -29,17 +29,17 @@ C ENDSR</pre>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>C SR102 BEGSR
<pre class="highlight"><code class="language-rpg" data-lang="rpg">C SR102 BEGSR
...
C ENDSR</pre>
C ENDSR</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre> /free
<pre class="highlight"><code class="language-rpg" data-lang="rpg"> /free
begsr SR103;
endsr;
/end-free</pre>
/end-free</code></pre>
</div>
</div>
</div>

View File

@ -1,3 +1,16 @@
<div class="paragraph">
<p>Shared naming conventions allow teams to collaborate efficiently. This rule checks that all function names match a provided regular expression.</p>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="paragraph">
<p>With default provided regular expression <code>^[a-z][a-zA-Z0-9]*$</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">public int DoSomething(){...}</code></pre>
</div>
</div>
</div>
</div>

View File

@ -1 +1,10 @@
include::description.adoc[]
== Noncompliant Code Example
With default provided regular expression ``++^[a-z][a-zA-Z0-9]*$++``:
[source, text]
----
public int DoSomething(){...}
----

View File

@ -4,6 +4,7 @@ include::../description.adoc[]
With default provided regular expression:
[source, scala]
----
def DoSomething( ) : Unit = { // Noncompliant
// ...
@ -12,6 +13,7 @@ def DoSomething( ) : Unit = { // Noncompliant
== Compliant Solution
[source, scala]
----
def doSomething( ) : Unit = {
// ...

View File

@ -9,9 +9,9 @@
</div>
<div class="listingblock">
<div class="content">
<pre>def DoSomething( ) : Unit = { // Noncompliant
<pre class="highlight"><code class="language-scala" data-lang="scala">def DoSomething( ) : Unit = { // Noncompliant
// ...
}</pre>
}</code></pre>
</div>
</div>
</div>
@ -21,9 +21,9 @@
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>def doSomething( ) : Unit = {
<pre class="highlight"><code class="language-scala" data-lang="scala">def doSomething( ) : Unit = {
// ...
}</pre>
}</code></pre>
</div>
</div>
</div>

View File

@ -1,3 +1,16 @@
<div class="paragraph">
<p>Shared naming conventions allow teams to collaborate efficiently. This rule checks that all function names match a provided regular expression.</p>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="paragraph">
<p>With default provided regular expression <code>^[a-z][a-zA-Z0-9]*$</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-text" data-lang="text">public int DoSomething(){...}</code></pre>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,55 @@
<div class="paragraph">
<p>If a function and a specialization of a function template are deemed equivalent after overload resolution, the non-specialized function will be chosen over the function specialization, which may be inconsistent with developer expectations.</p>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>void f ( short ); // Example 1
template &lt;typename T&gt; void f ( T ); // Example 2
void b ( short s )
{
f ( s ); // Noncompliant - Calls Example 1
f ( s + 1 ); // Noncompliant - Calls Example 2
}</pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_compliant_solution">Compliant Solution</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>void f ( short ); // Example 1
template &lt;typename T&gt; void f ( T ); // Example 2
void b ( short s )
{
f&lt;&gt;( s ); // Compliant - Explicitly calls Example 2
f&lt;&gt;( s + 1 ); // Compliant - Explicitly calls Example 2
}</pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_exceptions">Exceptions</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This rule does not apply to copy constructors or copy assignment operators.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_see">See</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>MISRA C&#43;&#43;:2008, 14-8-2</p>
</li>
</ul>
</div>
</div>
</div>

View File

@ -0,0 +1,30 @@
<div class="paragraph">
<p>Shared coding conventions allow teams to collaborate efficiently. This rule checks that all package names match a provided regular expression.</p>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="paragraph">
<p>With the default regular expression <code>^[a-z]+(\.[a-z][a-z0-9]*)*$</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>package org.Example { // Noncompliant
...
}</pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_compliant_solution">Compliant Solution</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>package org.example {
...
}</pre>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,26 @@
<div class="paragraph">
<p>Shared coding conventions allow teams to collaborate efficiently. This rule checks that all package names match a provided regular expression.</p>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="paragraph">
<p>With the default regular expression <code>^[a-z_]+(\.[a-z_][a-z0-9_]*)*$</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>package org.exAmple; // Noncompliant</pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_compliant_solution">Compliant Solution</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>package org.example;</pre>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,3 @@
<div class="paragraph">
<p>Shared coding conventions allow teams to collaborate efficiently. This rule checks that all package names match a provided regular expression.</p>
</div>

View File

@ -0,0 +1,44 @@
<div class="paragraph">
<p>88-level variables, also known as "condition name" variables, represent possible values of the "conditional variables" they&#8217;re tied to. An unused "condition name" variable is dead code. Such variables should be removed to increase the maintainability of the program.</p>
</div>
<div class="sect1">
<h2 id="_noncompliant_code_example">Noncompliant Code Example</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>01 COLOR PIC X.
88 COL-YELLOW VALUE 'Y'.
88 COL-GREEN VALUE 'G'. *&gt; Noncompliant; not used
88 COL-RED VALUE 'R'.
* ...
IF COL-YELLOW
* ...
END-IF
IF COL-RED
* ...
END-IF</pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_compliant_solution">Compliant Solution</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre>01 COLOR PIC X.
88 COL-YELLOW VALUE 'Y'.
88 COL-RED VALUE 'R'.
* ...
IF COL-YELLOW
* ...
END-IF
IF COL-RED
* ...
END-IF</pre>
</div>
</div>
</div>
</div>

View File

@ -7,6 +7,7 @@ from rspec_tools.cli import cli
from rspec_tools.rules import RulesRepository
import os
import re
class TestCLIValidateRulesMetadata:
'''Unit tests for metadata validation through Command Line Interface.'''
@ -79,5 +80,5 @@ class TestCLIValidateDescription:
def test_invalid_rule(self):
result = self._run_invalid(['S100'])
assert 'Validation failed due to 7 errors' in result.output
assert re.search(r'Validation failed due to \d+ errors', result.output)
assert result.exit_code == 1

View File

@ -7,7 +7,7 @@ from rspec_tools.errors import RuleValidationError
from copy import deepcopy
from rspec_tools.rules import LanguageSpecificRule, RulesRepository
from rspec_tools.validation.description import validate_section_names, validate_section_levels, validate_parameters
from rspec_tools.validation.description import validate_section_names, validate_section_levels, validate_parameters, validate_source_language
@pytest.fixture
def rule_language(mockrules: Path):
@ -62,3 +62,28 @@ def test_parameters_fails_validation_missing_description(invalid_rule):
'''Check that parameters without any description break validation.'''
with pytest.raises(RuleValidationError, match=fr'^Rule {rule.id} should have a description for each parameter'):
validate_parameters(rule)
def test_valid_source_declaration_validation(rule_language):
'''Check that declaring a language for sources is considered valid.'''
# cpp and text
validate_source_language(rule_language('S100', 'cfamily'))
# javascript and no source
validate_source_language(rule_language('S100', 'csharp'))
def test_missing_source_language_fails_validation(invalid_rule):
'''Check that forgetting the language for sources breaks validation'''
rule = invalid_rule('S100', 'cfamily')
with pytest.raises(RuleValidationError, match=re.escape(f'Rule {rule.id} has non highlighted code example in section "Noncompliant Code Example".\nUse [source,cpp] or [source,text] before the opening \'----\'.')):
validate_source_language(rule)
def test_missing_source_language_on_second_block_fails_validation(invalid_rule):
'''Check that forgetting the language for sources breaks validation in case of multiple blocks too'''
rule = invalid_rule('S100', 'java')
with pytest.raises(RuleValidationError, match=re.escape(f'Rule {rule.id} has non highlighted code example in section "Noncompliant Code Example".\nUse [source,java] or [source,text] before the opening \'----\'.')):
validate_source_language(rule)
def test_wrong_source_language_fails_validation(invalid_rule):
'''Check that forgetting the language for sources breaks validation'''
rule = invalid_rule('S100', 'csharp')
with pytest.raises(RuleValidationError, match=re.escape(f'Rule {rule.id} has unknown language "unknown" in code example in section "Noncompliant Code Example".\nAre you looking for "csharp"?')):
validate_source_language(rule)

View File

@ -4,6 +4,7 @@ include::../description.adoc[]
With default provided regular expression ``++^([A-Z0-9_]*|[a-z0-9_]*)$++``:
[source,abap]
----
METHOD MyMethod
...
@ -12,6 +13,7 @@ ENDMETHOD.
== Compliant Solution
[source,abap]
----
METHOD MY_METHOD
...

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With provided regular expression ``++^[a-z][a-zA-Z0-9_]*$++``:
[source,apex]
----
public void DoSomething(){...}
----
== Compliant Solution
[source,apex]
----
public void doSomething(){...}
----

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With default provided regular expression: ``++^[a-z][a-zA-Z0-9]*$++``:
[source,cpp]
----
void DoSomething (void);
----
== Compliant Solution
[source,cpp]
----
void doSomething (void);
----

View File

@ -2,12 +2,14 @@ Shared naming conventions allow teams to collaborate efficiently. This rule chec
== Noncompliant Code Example
[source,csharp]
----
public int doSomething() {...}
----
== Compliant Solution
[source,csharp]
----
public int DoSomething() {...}
----

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With default provided regular expression: ^[a-z][a-zA-Z0-9]*$
[source,flex]
----
function DoSomething(){...}
----
== Compliant Solution
[source,flex]
----
function doSomething(){...}
----

View File

@ -4,6 +4,7 @@ include::../description.adoc[]
With default provided regular expression: ``++^(_|[a-zA-Z0-9]+)$++``:
[source,go]
----
func execute_all() {
...
@ -12,6 +13,7 @@ func execute_all() {
== Compliant Solution
[source,go]
----
func executeAll() {
...

View File

@ -4,12 +4,14 @@ Shared naming conventions allow teams to collaborate efficiently. This rule chec
With default provided regular expression ``++^[a-z][a-zA-Z0-9]*$++``:
[source,java]
----
public int DoSomething(){...}
----
== Compliant Solution
[source,java]
----
public int doSomething(){...}
----

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With the default regular expression ``++^[a-z][a-zA-Z0-9]*$++``:
[source,javascript]
----
function DoSomething(){...} // Noncompliant
----
== Compliant Solution
[source,javascript]
----
function doSomething(){...}
----

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With default provided regular expression: ``++^[a-z][a-zA-Z0-9]*$++``:
[source,php]
----
function DoSomething(){...}
----
== Compliant Solution
[source,php]
----
function doSomething(){...}
----

View File

@ -4,6 +4,7 @@ Sharing some naming conventions is a key point to make it possible for a team to
With default provided regular expression: ``++^[a-z_][a-z0-9_]*$++``
[source,python]
----
class MyClass:
def MyMethod(a,b):
@ -12,6 +13,7 @@ class MyClass:
== Compliant Solution
[source,python]
----
class MyClass:
def my_method(a,b):

View File

@ -4,12 +4,14 @@ Sharing some naming conventions is a key point to make it possible for a team to
With default provided regular expression ``++^SR[a-zA-Z0-9]*$++``:
[source,rpg]
----
C XXXXX BEGSR
...
C ENDSR
----
[source,rpg]
----
/free
begsr yyyy;
@ -19,12 +21,14 @@ C ENDSR
== Compliant Solution
[source,rpg]
----
C SR102 BEGSR
...
C ENDSR
----
[source,rpg]
----
/free
begsr SR103;

View File

@ -4,6 +4,7 @@ include::../description.adoc[]
With default provided regular expression:
[source,scala]
----
def DoSomething( ) : Unit = { // Noncompliant
// ...
@ -12,6 +13,7 @@ def DoSomething( ) : Unit = { // Noncompliant
== Compliant Solution
[source,scala]
----
def doSomething( ) : Unit = {
// ...

View File

@ -3,6 +3,7 @@ An unnamed namespace will be unique within each translation unit. Any declaratio
== Noncompliant Code Example
[source,cpp]
----
// Header.hpp
namespace // Noncompliant
@ -11,6 +12,7 @@ namespace // Noncompliant
}
----
[source,cpp]
----
// File1.cpp
#include "Header.hpp"
@ -26,6 +28,7 @@ void fn_a(void)
}
----
[source,cpp]
----
// File2.cpp
#include "Header.hpp"

View File

@ -5,6 +5,7 @@ Using-declarations or fully-qualified names restricts the set of names considere
== Noncompliant Code Example
[source,cpp]
----
namespace NS1 {
int f();
@ -19,6 +20,7 @@ void g() {
== Compliant Solution
[source,cpp]
----
namespace NS1 {
int f();

View File

@ -9,6 +9,7 @@ A using declaration behaves in the same way but only for one name. Because of th
== Noncompliant Code Example
[source,cpp]
----
// f1.h
void foo ( char_t a );

View File

@ -2,6 +2,7 @@ include::../description.adoc[]
== Noncompliant Code Example
[source,flex]
----
function func1() { // Noncompliant - there are two points of exit
if (false) {
@ -19,6 +20,7 @@ function func2() { // Noncompliant - there are two points of exit
== Compliant Solution
[source,flex]
----
function func1() {
return;

View File

@ -1,5 +1,6 @@
== Noncompliant Code Example
[source,text]
----
int function1()
{

View File

@ -2,6 +2,7 @@ Procedures, unlike functions, do not return values. The ``++RETURN++`` statement
== Noncompliant Code Example
[source,sql]
----
SET SERVEROUTPUT ON

View File

@ -2,6 +2,7 @@ Overriding the default parameter value inherited from a parent class will lead t
== Noncompliant Code Example
[source,cpp]
----
enum E_ShapeColor {E_RED, E_GREEN, E_BLUE};
@ -30,6 +31,7 @@ int main() {
== Compliant Solution
[source,cpp]
----
enum E_ShapeColor {E_RED, E_GREEN, E_BLUE};

View File

@ -5,6 +5,7 @@ Default parameter values are useless in explicit interface implementations, beca
== Noncompliant Code Example
[source,csharp]
----
using System;
@ -42,6 +43,7 @@ public class Program
== Compliant Solution
[source,csharp]
----
using System;

View File

@ -6,6 +6,7 @@ The use of ``++wchar_t++`` as a bit-field type is prohibited as ISO/IEC 14882:20
== Noncompliant Code Example
[source,cpp]
----
struct S
{

View File

@ -3,6 +3,7 @@ The use of ``++enum++`` as a bit-field type is prohibited because ISO/IEC 14882:
== Noncompliant Code Example
[source,cpp]
----
struct S
{
@ -13,6 +14,7 @@ struct S
== Compliant Solution
[source,cpp]
----
struct S
{

View File

@ -4,6 +4,7 @@ include::../description.adoc[]
With the default provided regular expression ``++^([A-Z0-9_]*|[a-z0-9_]*)$++``:
[source,abap]
----
CLASS MyClass DEFINITION.
...
@ -12,6 +13,7 @@ ENDCLASS.
== Compliant Solution
[source,abap]
----
CLASS MY_CLASS DEFINITION.
...

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With default provided regular expression ``++^[A-Z][a-zA-Z0-9_]*$++``:
[source,apex]
----
class myClass {}
----
== Compliant Solution
[source,apex]
----
class MyClass {}
----

View File

@ -6,6 +6,7 @@ This rule allows to check that all class names (along with Objective-C interface
With default provided regular expression ``++^[A-Z][a-zA-Z0-9]*$++``:
[source,cpp]
----
// C++
class foo // Noncompliant
@ -19,6 +20,7 @@ class foo // Noncompliant
== Compliant Solution
[source,cpp]
----
// C++
class Foo // Compliant

View File

@ -1,5 +1,6 @@
== Compliant Solution
[source,text]
----
class MyClass {...}
----

View File

@ -2,6 +2,7 @@ Shared naming conventions allow teams to collaborate efficiently. This rule chec
== Noncompliant Code Example
[source,csharp]
----
class my_class {...}
class SOMEName42 {...}
@ -9,6 +10,7 @@ class SOMEName42 {...}
== Compliant Solution
[source,csharp]
----
class MyClass {...}
class SomeName42 {...}

View File

@ -4,12 +4,14 @@ include::../description.adoc[]
With default provided regular expression ``++^[A-Z][a-zA-Z0-9]*$++``:
[source,flex]
----
public class myClass {...}
----
== Compliant Solution
[source,flex]
----
public class MyClass {...}
----

View File

@ -10,12 +10,14 @@ Note that the casing of the first character determines if the type is exported o
With default provided regular expression ``++^[a-zA-Z][a-zA-Z0-9]*$++``:
[source,go]
----
type my_struct struct {...}
----
== Compliant Solution
[source,go]
----
type myStruct struct {...}
----

View File

@ -2,6 +2,7 @@
With default provided regular expression ``++^[A-Z][a-zA-Z0-9]*$++``:
[source,text]
----
class my_class {...}
----

View File

@ -7,6 +7,7 @@ The default regular expression is based on PEP-8 standard. It allows "CapWords"
With default provided regular expression ``++^_?([A-Z_][a-zA-Z0-9]*|[a-z_][a-z0-9_]*)$++``:
[source,python]
----
class myClass: # Noncompliant
...
@ -20,6 +21,7 @@ class my_CONTEXT_manager: # Noncompliant
== Compliant Solution
[source,python]
----
class MyClass:
...

View File

@ -4,6 +4,7 @@ include::../description.adoc[]
With default provided regular expression ``++^[A-Z][a-zA-Z0-9]*$++``:
[source,ruby]
----
class my_class
...
@ -12,6 +13,7 @@ end
== Compliant Solution
[source,ruby]
----
class MyClass
...

Some files were not shown because too many files have changed in this diff Show More