Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dart version update above 3 null safety #6

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6c85d0c
Linter rules config added
Aug 4, 2023
908a7f5
Conform framework to the Dart 3 version. Make tests pass.
Aug 5, 2023
41f0d38
Use native method containsKey to check existence of the value for com…
Aug 5, 2023
fabf4aa
Keyword new removed from code.
Aug 5, 2023
e40f5d2
Setter for multitonKey returned back
Aug 13, 2023
d344648
Keyword `new` returned to the comments in places where it was removed…
Aug 13, 2023
2775755
Observer setter corrected - proper target for value - _notifyContext
Aug 13, 2023
a1f0725
Comments `parts` in Unit_Tests.dart rearranged to top.
Aug 13, 2023
f42377d
Library 'dart:html' and related use of it removed from Unit_Tests as …
Aug 13, 2023
5457596
Add access modifiers for `notifyContext` and `notifyMethod` in Observer
Aug 13, 2023
433aaac
Unnecessary comment on registerProxy in Model removed.
Aug 13, 2023
f1c9c4e
Initialize multitoneKey with constructor input value `key` through se…
Aug 13, 2023
eec1bd8
Revert back test on observer.notifyContext
Aug 13, 2023
c8d0de4
Corrections in comments - [_multitonKey] => [multitonKey]
Aug 13, 2023
f7220a0
Use getter for `multitonKey` when commandInstance.initializeNotifier …
Aug 13, 2023
bf4cab2
Setting and accessing multitonKey from access modifiers in Facade con…
Aug 13, 2023
d14e870
Use access modifiers for multitonKey
Aug 13, 2023
1c82974
Open properties of Notification - name, body, type
Aug 13, 2023
db0122b
Comments added from previous versions of IObserver
Aug 13, 2023
357356b
Return back tests for properties of observer: observer.notifyMethod a…
Aug 13, 2023
bdfd798
README and VERSION update
Aug 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
835 changes: 831 additions & 4 deletions .gitignore

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ To use in your app, you can simply [add it to your project's pubspec.yaml as a d
* [Reverse Text](https://github.com/PureMVC/puremvc-dart-demo-reversetext/wiki)

## Status
Production - [Version 2.0.6](https://github.com/PureMVC/puremvc-dart-multicore-framework/blob/master/VERSION)
Production - [Version 2.0.7](https://github.com/PureMVC/puremvc-dart-multicore-framework/blob/master/VERSION)

## Platforms / Technologies
* [Google Dart](http://www.dartlang.org)

## License
* PureMVC MultiCore Framework for Dart (Ported) - Copyright � 2012-13 Cliff Hall
* PureMVC - Copyright � 2006-2013 [Futurescale, Inc](http://futurescale.com).
* PureMVC MultiCore Framework for Dart (Ported) - Copyright � 2012-13 Cliff Hall
* PureMVC - Copyright � 2006-2013 [Futurescale, Inc](http://futurescale.com).
* All rights reserved.

* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Expand Down
9 changes: 9 additions & 0 deletions VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ Release Date: 11/14/2013
Minor: 6
Authors: Cliff Hall <[email protected]>
--------------------------------------------------------------------------
2.0.7 Update code base to match requirements of mull-safety and Dart SDK version > 3.0.0
- environment: sdk: '^3.0.0'
- dependencies:
build_runner: any
build_web_compilers: any
Default Dart (Flutter) linter rules and code style corrections.
Many changes to internal processing of classes properties (through access modifiers).
Tests corrections to run unit tests and example.

2.0.6 Update pubspec.yaml
- environment: sdk: '>=0.8.10+6 <2.0.0'
- dependencies:
Expand Down
31 changes: 31 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# non_constant_identifier_names: false
# constant_identifier_names: false
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
64 changes: 30 additions & 34 deletions example/Framework_Verify.dart
Original file line number Diff line number Diff line change
@@ -1,79 +1,75 @@
import 'dart:html';

import 'package:puremvc/puremvc.dart' as mvc;

class Framework_Verify {
Framework_Verify() {}

Framework_Verify() {
}

void verify()
{
void verify() {
String multitonKey = "Test Core";
String dataPoint1 = "Hello";
String dataPoint2 = "World";
String proxyName = "DataProxy";
List<String> retrievedObject;
List<String>? retrievedObject;
String badJuju = "";

try {
write ("<UL>");
write("<UL>");

// Get a Facade
mvc.IFacade facade = mvc.Facade.getInstance( multitonKey );
write ("<LI>Facade created for ${multitonKey}.");
mvc.IFacade facade = mvc.Facade.getInstance(multitonKey)!;
write("<LI>Facade created for ${multitonKey}.");

// Create some data
List<String> dataObject = new List<String>();
write ("<LI>Data Object (List&ltString&gt) created.</LI>");
List<String> dataObject = List<String>.empty(growable: true);
write("<LI>Data Object (List&ltString&gt) created.</LI>");
dataObject.add(dataPoint1);
write ("<LI>Data point added '${dataPoint1}'.</LI>");
write("<LI>Data point added '${dataPoint1}'.</LI>");
dataObject.add(dataPoint2);
write ("<LI>Data point added '${dataPoint2}'.</LI>");
write("<LI>Data point added '${dataPoint2}'.</LI>");

// Register a Proxy to hold the data
mvc.IProxy proxy = new mvc.Proxy( proxyName, dataObject );
write( "<LI>Proxy '${proxyName}' created with for Data Object.</LI>");
facade.registerProxy( proxy );
write ("<LI>Proxy '${proxyName}' registered with Model, via Facade.</LI>");
mvc.IProxy proxy = mvc.Proxy(proxyName, dataObject);
write("<LI>Proxy '${proxyName}' created with for Data Object.</LI>");
facade.registerProxy(proxy);
write("<LI>Proxy '${proxyName}' registered with Model, via Facade.</LI>");

// Now retrieve the Proxy
mvc.IProxy retrievedProxy = facade.retrieveProxy( proxyName );
write ("<LI>Proxy '${proxyName}' retrieved from Model, via Facade.</LI>");
mvc.IProxy retrievedProxy = facade.retrieveProxy(proxyName);
write("<LI>Proxy '${proxyName}' retrieved from Model, via Facade.</LI>");

// And get the data
retrievedObject = retrievedProxy.getData();
write ("<LI>Data Object (List&ltString&gt) retrieved from ${proxyName}</LI>");
write("<LI>Data Object (List&ltString&gt) Length: ${retrievedObject.length}</LI>" );
write("<LI>Data Object (List&ltString&gt) retrieved from ${proxyName}</LI>");
write("<LI>Data Object (List&ltString&gt) Length: ${retrievedObject!.length}</LI>");
write("<LI>Contents: ${retrievedObject[0]} ${retrievedObject[1]}</LI>");

write ("</UL>");
write("</UL>");
// Prove errors will be reported
// throw "Fungers! I've got jelly in my ears!";

} on Error catch ( e ) {
} on Error catch (e) {
// Catch any error
badJuju = e.toString();

} finally {
// Report final status
if ( badJuju.length == 0 && retrievedObject != null
&& retrievedObject[0] == dataPoint1
&& retrievedObject[1] == dataPoint2 ){
write( "<P/><B>Science!</B> PureMVC is purring like a kitten. Take her out for a spin!");
if (badJuju.length == 0 &&
retrievedObject != null &&
retrievedObject[0] == dataPoint1 &&
retrievedObject[1] == dataPoint2) {
write("<P/><B>Science!</B> PureMVC is purring like a kitten. Take her out for a spin!");
} else {
write( "<P/><B>Claptrap!</B> Someone's thrown a spanner in the works.");
if( badJuju.length>0 ) write( "<B>Bad juju reported:</B> ${badJuju}");
write("<P/><B>Claptrap!</B> Someone's thrown a spanner in the works.");
if (badJuju.length > 0) write("<B>Bad juju reported:</B> ${badJuju}");
}
}

}

void write(String message) {
// the HTML library defines a global "document" variable
document.querySelector('#text').innerHtml = "${document.querySelector('#text').innerHtml}${message}";
document.querySelector('#text')?.innerHtml = "${document.querySelector('#text')?.innerHtml}${message}";
}
}

void main() {
new Framework_Verify().verify();
Framework_Verify().verify();
}
3 changes: 1 addition & 2 deletions example/Framework_Verify.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ <h2>Framework Verification Page</h2>
<p id="text"></p>
</div>

<script src="packages/browser/dart.js"></script>
<script type="application/dart" src="Framework_Verify.dart"/>
<script src="./Framework_Verify.dart.js"></script>
</body>
</html>
83 changes: 38 additions & 45 deletions lib/src/core/Controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ part of puremvc;
*
* See [INotification], [ICommand]
*/
class Controller implements IController
{

class Controller implements IController {
/**
* Constructor.
*
Expand All @@ -25,12 +23,11 @@ class Controller implements IController
*
* - Throws [MultitonErrorControllerExists] if instance for this Multiton key has already been constructed
*/
Controller( String key )
{
if ( instanceMap[ key ] != null ) throw new MultitonErrorControllerExists();
Controller(String key) {
if (instanceMap.containsKey(key)) throw MultitonErrorControllerExists();
multitonKey = key;
instanceMap[ multitonKey ] = this;
commandMap = new Map<String,Function>();
instanceMap[multitonKey] = this;
commandMap = Map<String, Function>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the above comment, commandMap and several other properties of the Multitons should be underscored as well. check the AS3 Reference for props that were protected or private.

initializeController();
}

Expand All @@ -43,22 +40,22 @@ class Controller implements IController
* you should also subclass [Controller] and override the [initializeController] method,
* setting [view] equal to the return value of a call to [getInstance] on your [IView] implementor.
*/
void initializeController( )
{
view = View.getInstance( multitonKey );
void initializeController() {
view = View.getInstance(multitonKey)!;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's one where it needs to be underscored but wasn't. It's going to be important to sweep all the classes and make sure all the props intended to be private/protected have underscores everywhere they're referenced.

}

/**
* [IController] Multiton Factory method.
*
* - Returns the [IController] Multiton instance for the specified key
*/
static IController getInstance( String key )
{
if ( key == null || key == "" ) return null;
if ( instanceMap == null ) instanceMap = new Map<String,IController>();
if ( instanceMap[ key ] == null ) instanceMap[ key ] = new Controller( key );
return instanceMap[ key ];
static IController? getInstance(String? key) {
if (key == null || key == "") return null;
if (instanceMap.containsKey(key)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this logic refactored? It may do the same thing in the end, but please, if possible, stick with the existing logic implementation, which was inherited from the AS3 port, which had years of improvement associated with it to eliminate hard to detect bugs. While one implementation might be as good as another, it's where new bugs can creep in. We'd like to make sure that we lean on the well-tested reference wherever we can, departing from it only when we have no other choice.

return instanceMap[key];
} else {
return instanceMap[key] = Controller(key);
}
}

/**
Expand All @@ -67,14 +64,14 @@ class Controller implements IController
*
* - Param [note] - the [INotification] to execute the associated [ICommand] for
*/
void executeCommand( INotification note )
{
Function commandFactory = commandMap[ note.getName() ];
if ( commandFactory == null ) return;
void executeCommand(INotification note) {
final noteName = note.getName();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another unnecessary departure from the original.

Function? commandFactory = commandMap[noteName];
if (commandFactory == null) return;

ICommand commandInstance = commandFactory();
commandInstance.initializeNotifier( multitonKey );
commandInstance.execute( note );
commandInstance.initializeNotifier(multitonKey);
commandInstance.execute(note);
}

/**
Expand All @@ -83,12 +80,11 @@ class Controller implements IController
* - Param [noteName] - the name of the [INotification] to associate the [ICommand] with.
* - Param [commandFactory] - a function that creates a new instance of the [ICommand].
*/
void registerCommand( String noteName, Function commandFactory )
{
if ( commandMap[ noteName ] == null ) {
view.registerObserver( noteName, new Observer( executeCommand, this ) );
void registerCommand(String noteName, Function commandFactory) {
if (!hasCommand(noteName)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stick with the original implementation wherever possible.

view.registerObserver(noteName, Observer(executeCommand, this));
}
commandMap[ noteName ] = commandFactory;
commandMap[noteName] = commandFactory;
}

/**
Expand All @@ -97,26 +93,23 @@ class Controller implements IController
* - Param [noteName] - the name of the [INotification].
* - Returns [bool] - whether an [ICommand] is currently registered for the given [noteName].
*/
bool hasCommand( String noteName )
{
return commandMap[ noteName ] != null;
bool hasCommand(String noteName) {
return commandMap.containsKey(noteName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert this to the original implementation.

I know, believe me, that this implementation makes sense. But there is a method to my madness.

One of the chief reasons that PureMVC has been ported to so many languages is that it eschews the syntactical sugar of any given language, and opts for the simplest (and therefore most widely supported) idioms.

If a language doesn't have a containsKey method on its native collection types, then a developer trying to port from this codebase, is forced to come up with an alternative implementation.

}

/**
* Remove a previously registered [INotification] to [ICommand] mapping from the [IController].
*
* - Param [noteName] - the name of the [INotification] to remove the [ICommand] mapping for.
*/
void removeCommand( String noteName )
{
void removeCommand(String noteName) {
// if the Command is registered...
if ( hasCommand( noteName ) )
{
if (hasCommand(noteName)) {
// remove the observer
view.removeObserver( noteName, this );
view.removeObserver(noteName, this);

// remove the command
commandMap[ noteName ] = null;
commandMap.remove(noteName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert to previous implementation

}
}

Expand All @@ -125,23 +118,23 @@ class Controller implements IController
*
* - Param [key] multitonKey of the [IController] instance to remove
*/
static void removeController( String key )
{
instanceMap[ key ] = null;
static void removeController(String key) {
instanceMap.remove(key);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert to previous implementation

}

// Local reference to this core's IView
IView view;
late IView view;

// Mapping of Notification names to Command Class references
Map<String,Function> commandMap;
late Map<String, Function?> commandMap;

// The Multiton Key for this Core
String multitonKey;
late String _multitonKey;
String get multitonKey => _multitonKey;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can drop this

void set multitonKey(value) => _multitonKey = value;

// Multiton instance map
static Map<String,IController> instanceMap;

static Map<String, IController> instanceMap = Map<String, IController>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this being initialized?

}

class MultitonErrorControllerExists {
Expand Down
Loading