Jump to content

KDevelop/SupportForDynamicMaps

From KDE Community Wiki

support for maps in dynamic languages

Virtually every dynamic language we can think of has some kind of map which you can use to store any combination of types. Currently there is no support for this in the KDevelop 4 DUChain. Here's a proposal we came up with on the KDevelop Hack Sprint 2009 in Ukraine:


UnsureType

essentially a list of possible types

MapType

A type which essentially holds two types: One for the key(s), one for the value(s).

AbstractType::Ptr MapType->keyType()
AbstractType::Ptr MapType->valueType()

In the simple case of a map similar to

QMap<KeyType, ValueType>

the types are clear. But in the following PHP example we would have to use UnsureType:

$a = array(
  1 => "foo",
  "bar" => 2134,
  0 => 0.234,
  "asdfasdf" => new someClass();
);
$a

would be a VariableDeclaration with an associated MapType. Here would be the expected return values for

keyType()

and

valueType()

respectivly:

  keyType() => UnsureType which contains the types
    ConstantIntegralType for Int, value 1
    ConstantIntegralType for String, value bar
    ConstantIntegralType for Int, value 0
    ConstantIntegralType for String, value asdfasdf
    • Note:** ConstantIntegralType has to be extended to be able to store strings. Should be simple by storing the IndexedString->index() in the available value field.
  valueType() => UnsureType which contains the types
    IntegralType for String
    IntegralType for Int
    IntegralType for Float
    StructureType for someClass

Declarations for map contents

Each map has its own context which contains declarations for all it's items.

The Declarations are again have a MapType, though keyType / valueType returns the real types, no UnsureType. As an Identifier we use the key converted to a string. Example: Int(1) => "1", String("asdf") => "\"asdf\""

    • TODO:** what / how do we store complex keys, for example variables, objects (possible in Ruby) or function calls.
// VariableDeclaration
//   type: MapType
//     MapType->keyType() => UnsureType (contains ConstIntegralType for Int and ConstIntegralType for String)
//     MapType->valueType() => UnsureType (contains ConstIntegralType for String, StructureType)
$a = array(
  // open new context for $a

  // Declaration
  //   type: MapType
  //     MapType->keyType() => ConstIntegralType Int, value 1
  //     MapType->valueType() => StructureType for Class
  //   Identifier: keyName (here: "1")
  //
  1 => "",

  // Declaration
  //   Type: MapType
  //     MapType->keyType() => ConstIntegralType String, value "a" (TODO:
  //     MapType->valueType() => StructureType for Class
  //   Identifier: keyName (here "\"a\"" <-- including the quotes, possibly in the PHP/Js case always converted to doublequotes
  "a" => new Class();

  // close context for $a
);

CodeCompletion:

All the above will make it possible to generate sane completion lists most of the time.

Example 1

$a[

This should create a list of all possible values for the keys, by going through keyType. ConstIntegralTypes list their values, StructureTypes (for Ruby) the identifier of their associated Declaration.

Example 2

$a = array(
  1 => new myClass();
  2 => ...
  ...
);

$a[1]->

Shows completion just like we access any variable of myClass type.

Example 3

In dynamic languages the following is possible which makes it a bit more complicated:

// in some config file e.g.
$a = array(
  0 => new class1,
  1 => new class2,
  2 => new class3,
  ...
);

// in another file
// we don't know what $b contains!
$a[$b]->

In this case we don't know how to resolve

$b

! Hence our idea is to give a list of all completionitems for each class

$a

contains. Since that is possibly quite much we show an additional list (positioned the same like the argument hint list) which can be accessed by mouse or by the up-arrow. That list contains all possible types (i.e. valueType()). This list can be used for filtering the lower list.