mirror of
https://github.com/dlang-community/D-Scanner.git
synced 2025-04-26 13:20:07 +03:00
update dmd and include the API needed for semantic analysis (#66)
* update dmd and include the API needed for semantic analysis * update libparse + initial implementation for properly documented public functions * test * refactor * update workflows * delete unused code
This commit is contained in:
parent
b90a8620ce
commit
cb432bc651
11 changed files with 581 additions and 717 deletions
7
.github/workflows/default.yml
vendored
7
.github/workflows/default.yml
vendored
|
@ -107,6 +107,10 @@ jobs:
|
|||
sudo apt-get install gdc-12 -y
|
||||
gdc-12 --version
|
||||
|
||||
# - name: Setup upterm session
|
||||
# if: ${{ matrix.build.type == 'make' && matrix.host == 'macos-latest'}}
|
||||
# uses: lhotari/action-upterm@v1
|
||||
|
||||
# Compile D-Scanner and execute all tests without dub
|
||||
- name: Build and test without dub
|
||||
if: ${{ matrix.build.type == 'make' }}
|
||||
|
@ -119,7 +123,8 @@ jobs:
|
|||
./build.bat
|
||||
./build.bat test
|
||||
else
|
||||
make "-j$(nproc)" all test
|
||||
NUM_PROC=$(nproc || getconf _NPROCESSORS_ONLN || 1)
|
||||
make "-j$((NUM_PROC / 2))" all test
|
||||
fi
|
||||
|
||||
# Compile D-Scanner and execute all tests using a specific dependency version
|
||||
|
|
28
build.bat
28
build.bat
|
@ -18,8 +18,8 @@ if %githashsize% == 0 (
|
|||
move /y bin\githash_.txt bin\githash.txt
|
||||
)
|
||||
|
||||
set DFLAGS=-O -release -version=StdLoggerDisableWarning -version=CallbackAPI -version=DMDLIB -version=MARS -Jbin -Jdmd %MFLAGS%
|
||||
set TESTFLAGS=-g -w -version=StdLoggerDisableWarning -version=CallbackAPI -version=DMDLIB -version=MARS -Jbin -Jdmd
|
||||
set DFLAGS=-O -release -version=StdLoggerDisableWarning -version=CallbackAPI -version=DMDLIB -version=MARS -Jbin -Jdmd -Jdmd\compiler\src\dmd\res %MFLAGS%
|
||||
set TESTFLAGS=-g -w -version=StdLoggerDisableWarning -version=CallbackAPI -version=DMDLIB -version=MARS -Jbin -Jdmd -Jdmd\compiler\src\dmd\res
|
||||
set CORE=
|
||||
set LIBDPARSE=
|
||||
set STD=
|
||||
|
@ -29,6 +29,8 @@ set DSYMBOL=
|
|||
set CONTAINERS=
|
||||
set LIBDDOC=
|
||||
|
||||
SET DMD_FRONTEND_SRC=objc_glue.obj clone.obj transitivevisitor.obj iasm.obj iasmdmd.obj canthrow.obj tokens.obj optimize.obj func.obj semantic2.obj dvarstats.obj ph2.obj code.obj cdef.obj xmm.obj out.obj elfobj.obj glocal.obj dvec.obj code_x86.obj iasm2.obj string2.obj file2.obj obj.obj go.obj inliner.obj cc.obj bcomplex.obj mscoffobj.obj ptrntab.obj dlist.obj pdata.obj fp.obj cod3.obj os.obj cgelem.obj dcode.obj disasm86.obj exh.obj blockopt.obj aarray.obj cg.obj newman.obj dwarfdbginf.obj codebuilder.obj var.obj cod2.obj machobj.obj cgobj.obj cod4.obj dtype.obj cv4.obj backend.obj el.obj cgcod.obj cv8.obj dwarf.obj evalu8.obj ty.obj mem.obj cgxmm.obj gdag.obj gother.obj goh.obj cgcv.obj debugprint.obj cgsched.obj dwarfeh.obj cgreg.obj backconfig.obj gloop.obj divcoeff.obj cod5.obj dwarf2.obj cg87.obj nteh.obj dcgcv.obj util2.obj compress.obj type.obj elpicpie.obj gsroa.obj cgcs.obj ee.obj symbol.obj barray.obj melf.obj oper.obj cgcse.obj rtlsym.obj mscoff.obj drtlsym.obj symtab.obj dt.obj mach.obj cod1.obj global.obj filespec.obj gflow.obj elem.obj cgen.obj md5.obj chkformat.obj argtypes_sysv_x64.obj sideeffect.obj denum.obj apply.obj e2ir.obj typinf.obj statement.obj arraytypes.obj blockexit.obj init.obj scanomf.obj utils.obj parsetimevisitor.obj errorsink.obj scanmscoff.obj initsem.obj arrayop.obj nogc.obj dsymbol.obj hdrgen.obj dmangle.obj astenums.obj libmscoff.obj compiler.obj foreachvar.obj scanmach.obj dcast.obj tocsym.obj tocvdebug.obj semantic3.obj builtin.obj sapply.obj printast.obj dtemplate.obj importc.obj file_manager.obj dclass.obj argtypes_x86.obj glue.obj statement_rewrite_walker.obj target.obj aggregate.obj stringtable.obj ctfloat.obj response.obj strtold.obj port.obj aav.obj env.obj optional.obj filename.obj man.obj rootobject.obj complex.obj hash.obj region.obj utf.obj speller.obj rmem.obj array.obj longdouble.obj bitarray.obj eh.obj strictvisitor.obj permissivevisitor.obj lambdacomp.obj ctfeexpr.obj cparse.obj imphint.obj delegatize.obj access.obj identifier.obj todt.obj dmsc.obj entity.obj impcnvtab.obj dimport.obj lexer.obj dinifile.obj libomf.obj vsoptions.obj dstruct.obj aliasthis.obj ctorflow.obj errors.obj astcodegen.obj mtype.obj dtoh.obj argtypes_aarch64.obj cpreprocess.obj dmdparams.obj lib.obj id.obj parse.obj doc.obj scanelf.obj iasmgcc.obj cppmanglewin.obj stmtstate.obj ob.obj expression.obj declaration.obj location.obj dinterpret.obj inline.obj bitfields.obj string.obj int128.obj file.obj outbuffer.obj nspace.obj gluelayer.obj json.obj toir.obj intrange.obj cond.obj constfold.obj dversion.obj staticassert.obj dmodule.obj traits.obj opover.obj link.obj toctype.obj staticcond.obj statementsem.obj globals.obj libmach.obj toobj.obj s2ir.obj inlinecost.obj objc.obj visitor.obj asttypename.obj mustuse.obj dsymbolsem.obj frontend.obj safe.obj dscope.obj attrib.obj ast_node.obj escape.obj cli.obj templateparamsem.obj libelf.obj console.obj cppmangle.obj astbase.obj dmacro.obj typesem.obj expressionsem.obj
|
||||
|
||||
set DMD_ROOT_SRC=
|
||||
for %%x in (dmd\compiler\src\dmd\common\*.d) do set DMD_ROOT_SRC=!DMD_ROOT_SRC! %%x
|
||||
for %%x in (dmd\compiler\src\dmd\root\*.d) do set DMD_ROOT_SRC=!DMD_ROOT_SRC! %%x
|
||||
|
@ -67,9 +69,21 @@ for %%x in (DCD\dsymbol\src\dsymbol\conversion\*.d) do set DSYMBOL=!DSYMBOL! %%x
|
|||
for %%x in (containers\src\containers\*.d) do set CONTAINERS=!CONTAINERS! %%x
|
||||
for %%x in (containers\src\containers\internal\*.d) do set CONTAINERS=!CONTAINERS! %%x
|
||||
|
||||
for %%x in (dmd\compiler\src\dmd\common\*.d) do %DC% %DFLAGS% -c %%x -od. -I"dmd\compiler\src"
|
||||
for %%x in (dmd\compiler\src\dmd\root\*.d) do %DC% %DFLAGS% -c %%x -od. -I"dmd\compiler\src"
|
||||
for %%x in (dmd\compiler\src\dmd\backend\*.d) do %DC% %DFLAGS% -c %%x -od. -I"dmd\compiler\src"
|
||||
for %%x in (dmd\compiler\src\dmd\*.d) do %DC% %DFLAGS% -c %%x -od. -I"dmd\compiler\src"
|
||||
|
||||
%DC% %DFLAGS% -c dmd\compiler\src\dmd\backend\iasm.d -od. -ofiasm2.obj -I"dmd\compiler\src"
|
||||
%DC% %DFLAGS% -c dmd\compiler\src\dmd\common\string.d -od. -ofstring2.obj -I"dmd\compiler\src"
|
||||
%DC% %DFLAGS% -c dmd\compiler\src\dmd\common\file.d -od. -offile2.obj -I"dmd\compiler\src"
|
||||
|
||||
if "%1" == "test" goto test_cmd
|
||||
|
||||
@echo on
|
||||
dir
|
||||
echo %DMD_FRONTEND_SRC%
|
||||
|
||||
%DC% %MFLAGS%^
|
||||
%CORE%^
|
||||
%STD%^
|
||||
|
@ -79,9 +93,7 @@ if "%1" == "test" goto test_cmd
|
|||
%INIFILED%^
|
||||
%DSYMBOL%^
|
||||
%CONTAINERS%^
|
||||
%DMD_ROOT_SRC%^
|
||||
%DMD_LEXER_SRC%^
|
||||
%DMD_PARSER_SRC%^
|
||||
%DMD_FRONTEND_SRC%^
|
||||
%DFLAGS%^
|
||||
-I"libdparse\src"^
|
||||
-I"DCD\dsymbol\src"^
|
||||
|
@ -102,14 +114,13 @@ set TESTNAME="bin\dscanner-unittest"
|
|||
%INIFILED%^
|
||||
%DSYMBOL%^
|
||||
%CONTAINERS%^
|
||||
%DMD_ROOT_SRC%^
|
||||
%DMD_LEXER_SRC%^
|
||||
%DMD_PARSER_SRC%^
|
||||
%DMD_FRONTEND_SRC%^
|
||||
-I"libdparse\src"^
|
||||
-I"DCD\dsymbol\src"^
|
||||
-I"containers\src"^
|
||||
-I"libddoc\src"^
|
||||
-I"dmd\compiler\src"^
|
||||
-I"dmd\compiler\src\dmd\res"^
|
||||
-lib %TESTFLAGS%^
|
||||
-of%TESTNAME%.lib
|
||||
if exist %TESTNAME%.lib %DC% %MFLAGS%^
|
||||
|
@ -124,6 +135,7 @@ if exist %TESTNAME%.lib %DC% %MFLAGS%^
|
|||
-I"libddoc\src"^
|
||||
-I"libddoc\common\source"^
|
||||
-I"dmd\compiler\src"^
|
||||
-I"dmd\compiler\src\dmd\res"^
|
||||
-unittest^
|
||||
%TESTFLAGS%^
|
||||
-of%TESTNAME%.exe
|
||||
|
|
2
dmd
2
dmd
|
@ -1 +1 @@
|
|||
Subproject commit 020685c85b4fde7d50511716dc98dfc5dc97ef2b
|
||||
Subproject commit a4220358ecfcffe7ea38ab4a1996ffc5a5331f22
|
7
dub.json
7
dub.json
|
@ -16,9 +16,10 @@
|
|||
"inifiled": "~>1.3.1",
|
||||
"emsi_containers": "~>0.9.0",
|
||||
"libddoc": "~>0.8.0",
|
||||
"dmd:root": "~master",
|
||||
"dmd:lexer": "~master",
|
||||
"dmd:parser": "~master"
|
||||
"dmd": {
|
||||
"repository": "git+https://github.com/dlang/dmd.git",
|
||||
"version": "a4220358ecfcffe7ea38ab4a1996ffc5a5331f22"
|
||||
}
|
||||
},
|
||||
"targetPath" : "bin",
|
||||
"stringImportPaths" : [
|
||||
|
|
28
makefile
28
makefile
|
@ -1,5 +1,7 @@
|
|||
.PHONY: all test clean
|
||||
|
||||
.DEFAULT_GOAL := all
|
||||
|
||||
DC ?= dmd
|
||||
GIT ?= git
|
||||
DMD := $(DC)
|
||||
|
@ -7,11 +9,19 @@ GDC := gdc
|
|||
LDC := ldc2
|
||||
DMD_ROOT_SRC := \
|
||||
$(shell find dmd/compiler/src/dmd/common -name "*.d")\
|
||||
$(shell find dmd/compiler/src/dmd/root -name "*.d")
|
||||
$(shell find dmd/compiler/src/dmd/root -name "*.d")\
|
||||
|
||||
DMD_FRONTEND_SRC := \
|
||||
$(shell find dmd/compiler/src/dmd/common -name "*.d")\
|
||||
$(shell find dmd/compiler/src/dmd/root -name "*.d")\
|
||||
$(shell find dmd/compiler/src/dmd/backend -name "*.d")\
|
||||
$(shell find dmd/compiler/src/dmd -maxdepth 1 -name "*.d" ! -name "mars.d" )
|
||||
|
||||
DMD_LEXER_SRC := \
|
||||
dmd/compiler/src/dmd/console.d \
|
||||
dmd/compiler/src/dmd/entity.d \
|
||||
dmd/compiler/src/dmd/errors.d \
|
||||
dmd/compiler/src/dmd/errorsink.d \
|
||||
dmd/compiler/src/dmd/file_manager.d \
|
||||
dmd/compiler/src/dmd/globals.d \
|
||||
dmd/compiler/src/dmd/id.d \
|
||||
|
@ -19,6 +29,7 @@ DMD_LEXER_SRC := \
|
|||
dmd/compiler/src/dmd/lexer.d \
|
||||
dmd/compiler/src/dmd/tokens.d \
|
||||
dmd/compiler/src/dmd/utils.d \
|
||||
dmd/compiler/src/dmd/location.d \
|
||||
$(DMD_ROOT_SRC)
|
||||
|
||||
DMD_PARSER_SRC := \
|
||||
|
@ -39,7 +50,8 @@ LIB_SRC := \
|
|||
$(shell find libdparse/src/dparse/ -name "*.d")\
|
||||
$(shell find libddoc/src -name "*.d") \
|
||||
$(shell find libddoc/common/source -name "*.d") \
|
||||
$(DMD_PARSER_SRC)
|
||||
$(DMD_FRONTEND_SRC)
|
||||
|
||||
PROJECT_SRC := $(shell find src/ -name "*.d")
|
||||
SRC := $(LIB_SRC) $(PROJECT_SRC)
|
||||
|
||||
|
@ -78,17 +90,17 @@ LDC_DEBUG_VERSIONS = -d-version=dparse_verbose
|
|||
GDC_VERSIONS = -fversion=StdLoggerDisableWarning -fversion=CallbackAPI -fversion=DMDLIB -fversion=MARS
|
||||
GDC_DEBUG_VERSIONS = -fversion=dparse_verbose
|
||||
|
||||
DC_FLAGS += -Jbin -Jdmd
|
||||
DC_FLAGS += -Jbin -Jdmd -Jdmd/compiler/src/dmd/res
|
||||
override DMD_FLAGS += $(DFLAGS) -w -release -O -od${OBJ_DIR}
|
||||
override LDC_FLAGS += $(DFLAGS) -O5 -release -oq
|
||||
override GDC_FLAGS += $(DFLAGS) -O3 -frelease -fall-instantiations
|
||||
|
||||
override GDC_TEST_FLAGS += -fall-instantiations
|
||||
|
||||
DC_TEST_FLAGS += -g -Jbin -Jdmd
|
||||
DC_TEST_FLAGS += -g -Jbin -Jdmd -Jdmd/compiler/src/dmd/res
|
||||
override DMD_TEST_FLAGS += -w
|
||||
|
||||
DC_DEBUG_FLAGS := -g -Jbin -Jdmd
|
||||
DC_DEBUG_FLAGS := -g -Jbin -Jdmd -Jdmd/compiler/src/dmd/res
|
||||
|
||||
ifeq ($(DC), $(filter $(DC), dmd ldmd2 gdmd))
|
||||
VERSIONS := $(DMD_VERSIONS)
|
||||
|
@ -113,7 +125,13 @@ SHELL:=/usr/bin/env bash
|
|||
|
||||
GITHASH = bin/githash.txt
|
||||
|
||||
FIRST_RUN_FLAG := $(OBJ_DIR)/$(DC)/first_run.flag
|
||||
|
||||
$(OBJ_DIR)/$(DC)/%.o: %.d
|
||||
if [ ! -f $(FIRST_RUN_FLAG) ]; then \
|
||||
${DC} -run dmd/config.d bin VERSION /etc; \
|
||||
touch $(FIRST_RUN_FLAG); \
|
||||
fi
|
||||
${DC} ${DC_FLAGS} ${VERSIONS} ${INCLUDE_PATHS} -c $< ${WRITE_TO_TARGET_NAME}
|
||||
|
||||
$(UT_OBJ_DIR)/$(DC)/%.o: %.d
|
||||
|
|
|
@ -10,6 +10,8 @@ import std.meta : AliasSeq;
|
|||
import std.string;
|
||||
import std.sumtype;
|
||||
import dmd.transitivevisitor;
|
||||
import dmd.visitor;
|
||||
import dmd.func;
|
||||
import core.stdc.string;
|
||||
import std.conv : to;
|
||||
|
||||
|
@ -909,9 +911,9 @@ unittest
|
|||
* Visitor that implements the AST traversal logic.
|
||||
* Supports collecting error messages
|
||||
*/
|
||||
extern(C++) class BaseAnalyzerDmd(AST) : ParseTimeTransitiveVisitor!AST
|
||||
extern(C++) class BaseAnalyzerDmd : SemanticTimeTransitiveVisitor
|
||||
{
|
||||
alias visit = ParseTimeTransitiveVisitor!AST.visit;
|
||||
alias visit = SemanticTimeTransitiveVisitor.visit;
|
||||
|
||||
extern(D) this(string fileName, bool skipTests = false)
|
||||
{
|
||||
|
@ -934,7 +936,7 @@ extern(C++) class BaseAnalyzerDmd(AST) : ParseTimeTransitiveVisitor!AST
|
|||
return _messages[].array;
|
||||
}
|
||||
|
||||
override void visit(AST.UnitTestDeclaration ud)
|
||||
override void visit(UnitTestDeclaration ud)
|
||||
{
|
||||
if (!skipTests)
|
||||
super.visit(ud);
|
||||
|
|
|
@ -22,6 +22,8 @@ import std.experimental.allocator.mallocator;
|
|||
|
||||
import dmd.parse : Parser;
|
||||
import dmd.astbase : ASTBase;
|
||||
import dmd.astcodegen;
|
||||
import dmd.frontend;
|
||||
|
||||
S between(S)(S value, S before, S after) if (isSomeString!S)
|
||||
{
|
||||
|
@ -471,3 +473,121 @@ void assertAnalyzerWarningsDMD(string code, const StaticAnalysisConfig config, b
|
|||
throw new AssertError(message, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
void assertAnalyzerWarningsDMD(string code, const StaticAnalysisConfig config, bool semantic = false,
|
||||
string file = __FILE__, size_t line = __LINE__)
|
||||
{
|
||||
import dmd.globals : global;
|
||||
import dscanner.utils : getModuleName;
|
||||
import std.file : remove, exists;
|
||||
import std.stdio : File;
|
||||
import std.path : dirName;
|
||||
import dmd.arraytypes : Strings;
|
||||
|
||||
import std.stdio : File;
|
||||
import std.file : exists, remove;
|
||||
|
||||
auto deleteme = "test.txt";
|
||||
File f = File(deleteme, "w");
|
||||
scope(exit)
|
||||
{
|
||||
assert(exists(deleteme));
|
||||
remove(deleteme);
|
||||
}
|
||||
|
||||
f.write(code);
|
||||
f.close();
|
||||
|
||||
auto dmdParentDir = dirName(dirName(dirName(dirName(__FILE_FULL_PATH__))));
|
||||
|
||||
global.params.useUnitTests = true;
|
||||
global.path = new Strings();
|
||||
global.path.push((dmdParentDir ~ "/dmd").ptr);
|
||||
global.path.push((dmdParentDir ~ "/dmd/druntime/src").ptr);
|
||||
|
||||
initDMD();
|
||||
|
||||
auto input = cast(char[]) code;
|
||||
input ~= '\0';
|
||||
auto t = dmd.frontend.parseModule(cast(const(char)[]) file, cast(const (char)[]) input);
|
||||
if (semantic)
|
||||
t.module_.fullSemantic();
|
||||
|
||||
MessageSet rawWarnings = analyzeDmd("test.txt", t.module_, getModuleName(t.module_.md), config);
|
||||
|
||||
string[] codeLines = code.splitLines();
|
||||
|
||||
// Get the warnings ordered by line
|
||||
string[size_t] warnings;
|
||||
foreach (rawWarning; rawWarnings[])
|
||||
{
|
||||
// Skip the warning if it is on line zero
|
||||
immutable size_t rawLine = rawWarning.line;
|
||||
if (rawLine == 0)
|
||||
{
|
||||
stderr.writefln("!!! Skipping warning because it is on line zero:\n%s",
|
||||
rawWarning.message);
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t warnLine = line - 1 + rawLine;
|
||||
warnings[warnLine] = format("[warn]: %s", rawWarning.message);
|
||||
}
|
||||
|
||||
// Get all the messages from the comments in the code
|
||||
string[size_t] messages;
|
||||
foreach (i, codeLine; codeLines)
|
||||
{
|
||||
// Skip if no [warn] comment
|
||||
if (codeLine.indexOf("// [warn]:") == -1)
|
||||
continue;
|
||||
|
||||
// Skip if there is no comment or code
|
||||
immutable string codePart = codeLine.before("// ");
|
||||
immutable string commentPart = codeLine.after("// ");
|
||||
if (!codePart.length || !commentPart.length)
|
||||
continue;
|
||||
|
||||
// Get the line of this code line
|
||||
size_t lineNo = i + line;
|
||||
|
||||
// Get the message
|
||||
messages[lineNo] = commentPart;
|
||||
}
|
||||
|
||||
// Throw an assert error if any messages are not listed in the warnings
|
||||
foreach (lineNo, message; messages)
|
||||
{
|
||||
// No warning
|
||||
if (lineNo !in warnings)
|
||||
{
|
||||
immutable string errors = "Expected warning:\n%s\nFrom source code at (%s:?):\n%s".format(messages[lineNo],
|
||||
lineNo, codeLines[lineNo - line]);
|
||||
throw new AssertError(errors, file, lineNo);
|
||||
}
|
||||
// Different warning
|
||||
else if (warnings[lineNo] != messages[lineNo])
|
||||
{
|
||||
immutable string errors = "Expected warning:\n%s\nBut was:\n%s\nFrom source code at (%s:?):\n%s".format(
|
||||
messages[lineNo], warnings[lineNo], lineNo, codeLines[lineNo - line]);
|
||||
throw new AssertError(errors, file, lineNo);
|
||||
}
|
||||
}
|
||||
|
||||
// Throw an assert error if there were any warnings that were not expected
|
||||
string[] unexpectedWarnings;
|
||||
foreach (lineNo, warning; warnings)
|
||||
{
|
||||
// Unexpected warning
|
||||
if (lineNo !in messages)
|
||||
{
|
||||
unexpectedWarnings ~= "%s\nFrom source code at (%s:?):\n%s".format(warning,
|
||||
lineNo, codeLines[lineNo - line]);
|
||||
}
|
||||
}
|
||||
if (unexpectedWarnings.length)
|
||||
{
|
||||
immutable string message = "Unexpected warnings:\n" ~ unexpectedWarnings.join("\n");
|
||||
throw new AssertError(message, file, line);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -97,6 +97,9 @@ import dscanner.reports : DScannerJsonReporter, SonarQubeGenericIssueDataReporte
|
|||
import dmd.astbase : ASTBase;
|
||||
import dmd.parse : Parser;
|
||||
|
||||
import dmd.frontend;
|
||||
import dmd.astcodegen;
|
||||
|
||||
bool first = true;
|
||||
|
||||
version (unittest)
|
||||
|
@ -393,25 +396,27 @@ bool analyze(string[] fileNames, const StaticAnalysisConfig config, string error
|
|||
import dmd.globals : global;
|
||||
import dmd.identifier : Identifier;
|
||||
import std.string : toStringz;
|
||||
|
||||
Id.initialize();
|
||||
global._init();
|
||||
global.params.useUnitTests = true;
|
||||
ASTBase.Type._init();
|
||||
|
||||
import dmd.arraytypes : Strings;
|
||||
|
||||
bool hasErrors;
|
||||
foreach (fileName; fileNames)
|
||||
{
|
||||
auto code = readFile(fileName);
|
||||
|
||||
auto id = Identifier.idPool(fileName);
|
||||
auto ast_m = new ASTBase.Module(fileName.toStringz, id, false, false);
|
||||
auto dmdParentDir = dirName(dirName(dirName(dirName(__FILE_FULL_PATH__))));
|
||||
|
||||
global.params.useUnitTests = true;
|
||||
global.path = new Strings();
|
||||
global.path.push((dmdParentDir ~ "/dmd").ptr);
|
||||
global.path.push((dmdParentDir ~ "/dmd/druntime/src").ptr);
|
||||
|
||||
initDMD();
|
||||
|
||||
auto code = readFile(fileName);
|
||||
auto input = cast(char[]) code;
|
||||
input ~= '\0';
|
||||
scope astbaseParser = new Parser!ASTBase(ast_m, input, false);
|
||||
astbaseParser.nextToken();
|
||||
ast_m.members = astbaseParser.parseModule();
|
||||
|
||||
auto t = dmd.frontend.parseModule(cast(const(char)[]) fileName, cast(const (char)[]) input);
|
||||
// t.module_.fullSemantic();
|
||||
|
||||
// Skip files that could not be read and continue with the rest
|
||||
if (code.length == 0)
|
||||
|
@ -426,7 +431,7 @@ bool analyze(string[] fileNames, const StaticAnalysisConfig config, string error
|
|||
if (errorCount > 0 || (staticAnalyze && warningCount > 0))
|
||||
hasErrors = true;
|
||||
MessageSet results = analyze(fileName, m, config, moduleCache, tokens, staticAnalyze);
|
||||
MessageSet resultsDmd = analyzeDmd(fileName, ast_m, getModuleName(astbaseParser.md), config);
|
||||
MessageSet resultsDmd = analyzeDmd(fileName, t.module_, getModuleName(t.module_.md), config);
|
||||
foreach (result; resultsDmd[])
|
||||
{
|
||||
results.insert(result);
|
||||
|
@ -739,7 +744,7 @@ bool shouldRun(check : BaseAnalyzer)(string moduleName, const ref StaticAnalysis
|
|||
*
|
||||
* If no includes are specified, all modules are included.
|
||||
*/
|
||||
bool shouldRunDmd(check : BaseAnalyzerDmd!ASTBase)(const char[] moduleName, const ref StaticAnalysisConfig config)
|
||||
bool shouldRunDmd(check : BaseAnalyzerDmd)(const char[] moduleName, const ref StaticAnalysisConfig config)
|
||||
{
|
||||
enum string a = check.name;
|
||||
|
||||
|
@ -921,10 +926,6 @@ private BaseAnalyzer[] getAnalyzersForModuleAndConfig(string fileName,
|
|||
checks ~= new AutoFunctionChecker(args.setSkipTests(
|
||||
analysisConfig.auto_function_check == Check.skipTests && !ut));
|
||||
|
||||
if (moduleName.shouldRun!ProperlyDocumentedPublicFunctions(analysisConfig))
|
||||
checks ~= new ProperlyDocumentedPublicFunctions(args.setSkipTests(
|
||||
analysisConfig.properly_documented_public_functions == Check.skipTests && !ut));
|
||||
|
||||
if (moduleName.shouldRun!VcallCtorChecker(analysisConfig))
|
||||
checks ~= new VcallCtorChecker(args.setSkipTests(
|
||||
analysisConfig.vcall_in_ctor == Check.skipTests && !ut));
|
||||
|
@ -1265,77 +1266,83 @@ version (unittest)
|
|||
}
|
||||
}
|
||||
|
||||
MessageSet analyzeDmd(string fileName, ASTBase.Module m, const char[] moduleName, const StaticAnalysisConfig config)
|
||||
MessageSet analyzeDmd(string fileName, ASTCodegen.Module m, const char[] moduleName, const StaticAnalysisConfig config)
|
||||
{
|
||||
MessageSet set = new MessageSet;
|
||||
BaseAnalyzerDmd!ASTBase[] visitors;
|
||||
BaseAnalyzerDmd[] visitors;
|
||||
|
||||
if (moduleName.shouldRunDmd!(ObjectConstCheck!ASTBase)(config))
|
||||
visitors ~= new ObjectConstCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(ObjectConstCheck!ASTCodegen)(config))
|
||||
visitors ~= new ObjectConstCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(EnumArrayVisitor!ASTBase)(config))
|
||||
visitors ~= new EnumArrayVisitor!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(EnumArrayVisitor!ASTCodegen)(config))
|
||||
visitors ~= new EnumArrayVisitor!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(DeleteCheck!ASTBase)(config))
|
||||
visitors ~= new DeleteCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(DeleteCheck!ASTCodegen)(config))
|
||||
visitors ~= new DeleteCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(FinalAttributeChecker!ASTBase)(config))
|
||||
visitors ~= new FinalAttributeChecker!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(FinalAttributeChecker!ASTCodegen)(config))
|
||||
visitors ~= new FinalAttributeChecker!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(ImportSortednessCheck!ASTBase)(config))
|
||||
visitors ~= new ImportSortednessCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(ImportSortednessCheck!ASTCodegen)(config))
|
||||
visitors ~= new ImportSortednessCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(IncorrectInfiniteRangeCheck!ASTBase)(config))
|
||||
visitors ~= new IncorrectInfiniteRangeCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(IncorrectInfiniteRangeCheck!ASTCodegen)(config))
|
||||
visitors ~= new IncorrectInfiniteRangeCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(RedundantAttributesCheck!ASTBase)(config))
|
||||
visitors ~= new RedundantAttributesCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(RedundantAttributesCheck!ASTCodegen)(config))
|
||||
visitors ~= new RedundantAttributesCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(LengthSubtractionCheck!ASTBase)(config))
|
||||
visitors ~= new LengthSubtractionCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(LengthSubtractionCheck!ASTCodegen)(config))
|
||||
visitors ~= new LengthSubtractionCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(AliasSyntaxCheck!ASTBase)(config))
|
||||
visitors ~= new AliasSyntaxCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(AliasSyntaxCheck!ASTCodegen)(config))
|
||||
visitors ~= new AliasSyntaxCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(ExplicitlyAnnotatedUnittestCheck!ASTBase)(config))
|
||||
visitors ~= new ExplicitlyAnnotatedUnittestCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(ExplicitlyAnnotatedUnittestCheck!ASTCodegen)(config))
|
||||
visitors ~= new ExplicitlyAnnotatedUnittestCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(ConstructorCheck!ASTBase)(config))
|
||||
visitors ~= new ConstructorCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(ConstructorCheck!ASTCodegen)(config))
|
||||
visitors ~= new ConstructorCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(AssertWithoutMessageCheck!ASTBase)(config))
|
||||
visitors ~= new AssertWithoutMessageCheck!ASTBase(
|
||||
if (moduleName.shouldRunDmd!(AssertWithoutMessageCheck!ASTCodegen)(config))
|
||||
visitors ~= new AssertWithoutMessageCheck!ASTCodegen(
|
||||
fileName,
|
||||
config.assert_without_msg == Check.skipTests && !ut
|
||||
);
|
||||
|
||||
if (moduleName.shouldRunDmd!(LocalImportCheck!ASTBase)(config))
|
||||
visitors ~= new LocalImportCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(LocalImportCheck!ASTCodegen)(config))
|
||||
visitors ~= new LocalImportCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(OpEqualsWithoutToHashCheck!ASTBase)(config))
|
||||
visitors ~= new OpEqualsWithoutToHashCheck!ASTBase(
|
||||
if (moduleName.shouldRunDmd!(OpEqualsWithoutToHashCheck!ASTCodegen)(config))
|
||||
visitors ~= new OpEqualsWithoutToHashCheck!ASTCodegen(
|
||||
fileName,
|
||||
config.opequals_tohash_check == Check.skipTests && !ut
|
||||
);
|
||||
|
||||
if (moduleName.shouldRunDmd!(AutoRefAssignmentCheck!ASTBase)(config))
|
||||
visitors ~= new AutoRefAssignmentCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(AutoRefAssignmentCheck!ASTCodegen)(config))
|
||||
visitors ~= new AutoRefAssignmentCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(LogicPrecedenceCheck!ASTBase)(config))
|
||||
visitors ~= new LogicPrecedenceCheck!ASTBase(
|
||||
if (moduleName.shouldRunDmd!(LogicPrecedenceCheck!ASTCodegen)(config))
|
||||
visitors ~= new LogicPrecedenceCheck!ASTCodegen(
|
||||
fileName,
|
||||
config.logical_precedence_check == Check.skipTests && !ut
|
||||
);
|
||||
|
||||
if (moduleName.shouldRunDmd!(BuiltinPropertyNameCheck!ASTBase)(config))
|
||||
visitors ~= new BuiltinPropertyNameCheck!ASTBase(fileName);
|
||||
if (moduleName.shouldRunDmd!(BuiltinPropertyNameCheck!ASTCodegen)(config))
|
||||
visitors ~= new BuiltinPropertyNameCheck!ASTCodegen(fileName);
|
||||
|
||||
if (moduleName.shouldRunDmd!(BackwardsRangeCheck!ASTBase)(config))
|
||||
visitors ~= new BackwardsRangeCheck!ASTBase(
|
||||
if (moduleName.shouldRunDmd!(BackwardsRangeCheck!ASTCodegen)(config))
|
||||
visitors ~= new BackwardsRangeCheck!ASTCodegen(
|
||||
fileName,
|
||||
config.backwards_range_check == Check.skipTests && !ut
|
||||
);
|
||||
|
||||
if (moduleName.shouldRunDmd!(ProperlyDocumentedPublicFunctions!ASTCodegen)(config))
|
||||
visitors ~= new ProperlyDocumentedPublicFunctions!ASTCodegen(
|
||||
fileName,
|
||||
config.properly_documented_public_functions == Check.skipTests && !ut
|
||||
);
|
||||
|
||||
foreach (visitor; visitors)
|
||||
{
|
||||
m.accept(visitor);
|
||||
|
|
|
@ -50,6 +50,8 @@ extern(C++) class ImportVisitor(AST) : ParseTimeTransitiveVisitor!AST
|
|||
|
||||
private void visitFile(bool usingStdin, string fileName, RedBlackTree!string importedModules)
|
||||
{
|
||||
import dmd.errorsink : ErrorSinkNull;
|
||||
|
||||
Id.initialize();
|
||||
global._init();
|
||||
global.params.useUnitTests = true;
|
||||
|
@ -60,7 +62,11 @@ private void visitFile(bool usingStdin, string fileName, RedBlackTree!string imp
|
|||
ubyte[] bytes = usingStdin ? readStdin() : readFile(fileName);
|
||||
auto input = cast(char[]) bytes;
|
||||
|
||||
scope p = new Parser!ASTBase(m, input, false);
|
||||
__gshared ErrorSinkNull errorSinkNull;
|
||||
if (!errorSinkNull)
|
||||
errorSinkNull = new ErrorSinkNull;
|
||||
|
||||
scope p = new Parser!ASTBase(m, input, false, new ErrorSinkNull, null, false);
|
||||
p.nextToken();
|
||||
m.members = p.parseModule();
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import std.path: isValidPath;
|
|||
|
||||
import dmd.astbase : ASTBase;
|
||||
import dmd.parse : Parser;
|
||||
import dmd.astcodegen;
|
||||
|
||||
private void processBOM(ref ubyte[] sourceCode, string fname)
|
||||
{
|
||||
|
@ -316,14 +317,14 @@ auto ref safeAccess(M)(M m)
|
|||
/**
|
||||
* Return the module name from a ModuleDeclaration instance with the following format: `foo.bar.module`
|
||||
*/
|
||||
const(char[]) getModuleName(ASTBase.ModuleDeclaration *mdptr)
|
||||
const(char[]) getModuleName(ASTCodegen.ModuleDeclaration *mdptr)
|
||||
{
|
||||
import std.array : array, join;
|
||||
|
||||
if (mdptr !is null)
|
||||
{
|
||||
import std.algorithm : map;
|
||||
ASTBase.ModuleDeclaration md = *mdptr;
|
||||
ASTCodegen.ModuleDeclaration md = *mdptr;
|
||||
|
||||
if (md.packages.length != 0)
|
||||
return join(md.packages.map!(e => e.toString()).array ~ md.id.toString().dup, ".");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue