D-Scanner/types.d

550 lines
12 KiB
D
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright Brian Schott (Sir Alaran) 2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module types;
import std.stdio;
import std.array;
import std.range;
import std.algorithm;
import std.typecons;
/**
* Returns: s with any quote characters backslash-escaped
*/
string escapeJSON(string s)
{
return s.replace("\"", "\\\"");
}
unittest { assert(escapeJSON("abc\"def") == "abc\\\"def"); }
/**
* Writes a string in JSON fromat to the given file
* Params:
* f = the file to write to
* name = the name of the json attribute
* value = the value of the json attribute
* indent = the indent level
*/
void writeJSONString(File f, const string name, const string value, uint indent = 0)
{
f.write(std.array.replicate(" ", indent), "\"", name, "\" : \"", escapeJSON(value), "\"");
}
/**
* Writes a string array in JSON format to the given file
* f = the file to write to
* name = the name of the json attribute
* values = the strings that should be written
* indent = the indent level
*/
void writeJSONString(File f, const string name, const string[] values, uint indent = 0)
{
f.writeln(std.array.replicate(" ", indent), "\"", name, "\" : [");
foreach(i, v; values)
{
f.write(std.array.replicate(" ", indent + 1), "\"", escapeJSON(v), "\"");
if (i + 1 < values.length)
f.writeln(",");
else
f.writeln();
}
f.write(std.array.replicate(" ", indent), "]");
}
/**
* Attributes common to everything interesting
*/
abstract class Base
{
public:
/// Sybol name
string name;
/// Line number of declaration
uint line;
/// Attributes such as "ref", "const", etc.
string[] attributes;
/// Protection level such as "public", protected, etc.
string protection;
/// See_also: writeJSONString
void writeJSONTo(File f, uint indent) const
{
f.writeln(std.array.replicate(" ", indent + 1), "{");
printMembers(f, indent + 2);
f.write("\n", std.array.replicate(" ", indent + 1), "}");
}
protected:
void printMembers(File f, uint indent = 0) const
{
writeJSONString(f, "name", name, indent);
f.writeln(",");
f.write(std.array.replicate(" ", indent), "\"line\" : ", line);
f.writeln(",");
writeJSONString(f, "protection", protection, indent);
f.writeln(",");
writeJSONString(f, "attributes", attributes, indent);
}
}
/**
* Varible declaration
*/
class Variable : Base
{
public:
/// Variable type
string type;
protected:
override void printMembers(File f, uint indent = 0) const
{
super.printMembers(f, indent);
f.writeln(",");
writeJSONString(f, "type", type, indent);
}
}
/**
* Base class for any type that can be a template
*/
abstract class Templateable : Base
{
public:
/// Template constraint, which may be null
string constraint;
/// Template parameters, may be empty
string[] templateParameters;
protected:
override void printMembers(File f, uint indent = 0) const
{
super.printMembers(f, indent);
f.writeln(",");
writeJSONString(f, "constraint", constraint, indent);
f.writeln(",");
writeJSONString(f, "templateParameters", templateParameters, indent);
}
}
/**
* Stuff common to struct, interface, and class.
*/
class Struct : Templateable
{
public:
/// List of methods
Function[] functions;
/// List of member variables; may be empty
Variable[] variables;
/// Source code character position of the beginning of the struct body
size_t bodyStart;
/// Source code character position of the end of the struct body
size_t bodyEnd;
string getMemberType(string name) const
{
foreach (f; functions)
if (f.name == name)
return f.returnType;
foreach (v; variables)
if (v.name == name)
return v.type;
return null;
}
protected:
override void printMembers(File f, uint indent = 0) const
{
super.printMembers(f, indent);
f.writeln(",\n", std.array.replicate(" ", indent), "\"functions\" : [");
foreach(i, fun; functions)
{
fun.writeJSONTo(f, indent);
if (i + 1 < functions.length)
f.writeln(",");
else
f.writeln();
}
f.writeln(std.array.replicate(" ", indent), "],\n", std.array.replicate(" ", indent), "\"variables\" : [");
foreach(i, var; variables)
{
var.writeJSONTo(f, indent);
if (i + 1 < variables.length)
f.writeln(",");
else
f.writeln();
}
f.write(std.array.replicate(" ", indent), "]");
}
}
/**
* Functions and delegates
*/
class Function : Templateable
{
public:
/// Function return type
string returnType;
/// Parameter list; may be empty
Variable[] parameters;
protected:
override void printMembers(File f, uint indent) const
{
super.printMembers(f, indent);
f.write(",\n");
f.writeln(std.array.replicate(" ", indent), "\"parameters\" : [");
foreach(i, params; parameters)
{
params.writeJSONTo(f, indent);
if (i + 1 < parameters.length)
f.writeln(",");
else
f.writeln();
}
f.write(std.array.replicate(" ", indent), "],\n");
writeJSONString(f, "returnType", returnType, indent);
}
}
/**
* class and interface
*/
class Inherits : Struct
{
public:
/**
* List of interfaces and classes that this inherits or implements; may
* be empty
*/
string[] baseClasses;
protected:
override void printMembers(File f, uint indent = 0) const
{
super.printMembers(f, indent);
f.writeln(",");
writeJSONString(f, "baseClasses", baseClasses, indent);
}
}
/**
* enum member
*/
struct EnumMember
{
uint line;
string name;
}
/**
* enum
*/
class Enum : Base
{
public:
/// Base type for this enum
string type;
/// Enum members; may be empty
EnumMember[] members;
protected:
override void printMembers(File f, uint indent = 0) const
{
super.printMembers(f, indent);
f.writeln(",");
writeJSONString(f, "type", type, indent);
f.writeln(",\n", std.array.replicate(" ", indent), "\"members\" : [");
foreach(i, member; members)
{
f.writeln(std.array.replicate(" ", indent + 1), "{");
writeJSONString(f, "name", member.name, indent + 2);
f.writeln(",");
f.writeln(std.array.replicate(" ", indent + 2), "\"line\" : ", member.line);
f.write(std.array.replicate(" ", indent + 1), "}");
if (i + 1 < members.length)
f.writeln(",");
else
f.writeln();
}
f.write(std.array.replicate(" ", indent), "]");
}
}
/**
* Module is a container class for the other classes
*/
class Module
{
public:
/// Module name. Will be blank if there is no module statement
string name;
/// List of interfaces declared in this module
Inherits[] interfaces;
/// List of classes declared in this module
Inherits[] classes;
/// List of functions declared in this module
Function[] functions;
/// List of unions declared in this module
Struct[] unions;
/// List of variables declared in this module
Variable[] variables;
/// List of structs declared in this module
Struct[] structs;
/// List of enums declared in this module
Enum[] enums;
/// List of other modules that are imported by this one
string[] imports;
/// Combine this module with another one
void merge(Module other)
{
interfaces.insertInPlace(interfaces.length, other.interfaces);
classes.insertInPlace(classes.length, other.classes);
functions.insertInPlace(functions.length, other.functions);
unions.insertInPlace(unions.length, other.unions);
variables.insertInPlace(variables.length, other.variables);
structs.insertInPlace(structs.length, other.structs);
enums.insertInPlace(enums.length, other.enums);
imports.insertInPlace(imports.length, other.imports);
}
/**
* Prints a JSON representation of this module to the given file
*/
void writeJSONTo(File f) const
{
uint indent = 0;
f.writeln("{");
writeJSONString(f, "name", name, indent + 1);
f.writeln(",");
writeJSONString(f, "imports", imports, indent + 1);
f.writeln(",\n \"interfaces\" : [");
foreach(i, inter; interfaces)
{
inter.writeJSONTo(f, indent + 1);
if (i + 1 < interfaces.length)
f.writeln(",");
else
f.writeln();
}
f.writeln(" ],\n \"classes\" : [");
foreach(i, cl; classes)
{
cl.writeJSONTo(f, indent + 1);
if (i + 1 < classes.length)
f.writeln(",");
else
f.writeln();
}
f.writeln(" ],\n \"structs\" : [");
foreach(i, str; structs)
{
str.writeJSONTo(f, indent + 1);
if (i + 1 < structs.length)
f.writeln(",");
else
f.writeln();
}
f.writeln(" ],\n \"structs\" : [");
foreach(i, un; unions)
{
un.writeJSONTo(f, indent + 1);
if (i + 1 < unions.length)
f.writeln(",");
else
f.writeln();
}
f.writeln(" ],\n \"functions\" : [");
foreach(i, fun; functions)
{
fun.writeJSONTo(f, indent + 1);
if (i + 1 < functions.length)
f.writeln(",");
else
f.writeln();
}
f.writeln(" ],\n \"variables\" : [");
foreach(i, var; variables)
{
var.writeJSONTo(f, indent + 1);
if (i + 1 < variables.length)
f.writeln(",");
else
f.writeln();
}
f.writeln(" ],\n \"enums\" : [");
foreach(i, en; enums)
{
en.writeJSONTo(f, indent + 1);
if (i + 1 < enums.length)
f.writeln(",");
else
f.writeln();
}
f.writeln(" ]\n}");
}
}
immutable(string[][string]) typeProperties;
immutable(string[]) floatProperties;
immutable(string[]) integralProperties;
immutable(string[]) commonProperties;
immutable(string[]) arrayProperties;
static this()
{
floatProperties = ["alignof", "dig", "epsilon", "im", "infinity", "init",
"mangleof", "mant_dig", "max", "max_10_exp", ".max_­exp", "min_10_­exp",
"min_­exp", "min_nor­mal", "nan", "re", "sizeof"
];
integralProperties = ["alignof", "init", "mangleof", "max",
"min", "sizeof", "stringof"
];
commonProperties = [
"alignof",
"init",
"mangleof",
"stringof"
];
arrayProperties = [
"alignof",
"init",
"length",
"mangleof",
"ptr",
"stringof",
];
typeProperties = [
"bool" : commonProperties,
"byte" : integralProperties,
"ubyte" : integralProperties,
"short" : integralProperties,
"ushort" : integralProperties,
"int" : integralProperties,
"uint" : integralProperties,
"long" : integralProperties,
"ulong" : integralProperties,
"cent" : integralProperties,
"ucent" : integralProperties,
"float" : floatProperties,
"dou­ble" : floatProperties,
"real" : floatProperties,
"ifloat" : floatProperties,
"idou­ble" : floatProperties,
"ireal" : floatProperties,
"cfloat" : floatProperties,
"cdou­ble" : floatProperties,
"creal" : floatProperties,
"char" : commonProperties,
"wchar" : commonProperties,
"dchar" : commonProperties,
"ptrdiff_t" : integralProperties,
"size_t" : integralProperties,
"string" : arrayProperties,
"wstring" : arrayProperties,
"dstring" : arrayProperties
];
}
class CompletionContext
{
public:
this(Module mod)
{
this.currentModule = mod;
}
Tuple!(string, string)[string] getMembersOfType(string name)
{
foreach (m; chain(modules, [currentModule]))
{
foreach (s; chain(m.structs, m.interfaces, m.classes, m.unions))
{
if (s.name != name)
continue;
Tuple!(string, string)[string] typeMap;
foreach(var; s.variables)
typeMap[var.name] = Tuple!(string, string)(var.type, "?1");
foreach(fun; s.functions)
typeMap[fun.name] = Tuple!(string, string)(fun.returnType, "?2");
return typeMap;
}
foreach (Enum e; m.enums)
{
if (e.name != name)
continue;
Tuple!(string, string)[string] typeMap;
foreach (member; e.members)
typeMap[member.name] = Tuple!(string, string)(e.type, "?1");
return typeMap;
}
}
return null;
}
Struct[] getStructsContaining(size_t cursorPosition)
{
auto app = appender!(Struct[])();
foreach(s; chain(currentModule.structs, currentModule.interfaces,
currentModule.classes, currentModule.unions))
{
if (s.bodyStart <= cursorPosition && s.bodyEnd >= cursorPosition)
app.put(s);
}
return app.data();
}
void addModule(Module mod)
{
modules ~= mod;
}
Module currentModule;
Module[] modules;
}